JavaScript基礎概念之----跨域

瀏覽器對於javascript的同源策略的限制,出現了跨域。javascript

只要協議、域名、端口等不一樣,就會出現跨域:以下html

域名:
 主域名不一樣 http://www.a.com –>http://www.b.com
 子域名不一樣 http://www.m.a.com/index.html –>http://www.n.a.com/test.js
 域名和域名ip http://www.a.com/index.html –>http://188.44.77.98/test.js
端口:
 http://www.a.com:8080/index.html–> http://www.a.com:9090/test.js
協議:
 http://www.a.com:8080/index.html–> https://www.a.com:8080/test.js
其餘:
 一、端口和協議的不一樣,只能經過後臺來解決
 二、localhost和127.0.0.1雖然都指向本機,但也屬於跨域html5

解決跨域有下面幾種方法:java

  • jsonp跨域(JSON with Padding 填充式JSON)
  • document.domain
  • wndow.name
  • postMessage
  • 後端修改header
  • nginx反向代理

JSONP跨域jquery

只支持get請求。返回的是腳本代碼(包含一個函數調用)。nginx

經過script標籤引入一個js文件,這個js文件載入成功後會執行咱們在url參數中指定的函數,而且會把咱們須要的json數據做爲參數傳入。因此jsonp是須要服務器端的頁面進行相應的配合的。json

<script>
function dosomething(jsonData){
    //處理得到的json數據
}
</script>
<script src="http://xxx.com/test.jsp?callback=dosomething"></script>

知道jsonp跨域的原理後咱們就能夠用js動態生成script標籤來進行跨域操做了,而不用特地的手動的書寫那些script標籤。若是你的頁面使用jquery,那麼經過它封裝的方法就能很方便的來進行jsonp操做了。segmentfault

<script>
$.getJSON('http://xxx.com/data.jsp?callback=?',function(jsonData){
    //處理得到的JSON數據
})
</script>

document.domain後端

瀏覽器中不一樣域的框架之間是不能進行js的交互操做的。api

好比,有一個頁面,它的地址是http://www.example.com/a.html  , 在這個頁面裏面有一個iframe,它的src是http://example.com/b.html, 很顯然,這個頁面與它裏面的iframe框架是不一樣域的,因此咱們是沒法經過在頁面中書寫js代碼來獲取iframe中的東西的:

<script>
function onload(){
    var iframe = document.getElementById('iframe')
    
    //這裏能獲取到iframe裏的window,但該window的屬性和方法是不可用的
    var win = iframe.contentWindow
    //這裏獲取不到iframe裏的document
    var doc = win.document
    //這裏獲取不到window的name
    var name = win.name
</script>
<iframe id="iframe" src="http://example.com/b.html" onload="onload()"></iframe>

咱們只要把http://www.example.com/a.htmlhttp://example.com/b.html這兩個頁面的document.domain都設成相同的域名就能夠了。但要注意的是,document.domain的設置是有限制的,咱們只能把document.domain設置成自身或更高一級的父域,且主域必須相同。

在頁面 http://www.example.com/a.html 中設置document.domain:

<iframe id="iframe" src="http://example.com/b.html" onload="test()"></iframe>
<script>
document.domain = 'example.com'; // 設置成主域
function test(){
    alert(document.getElementById('iframe').contentWindow)
</script>

在頁面 http://example.com/b.html 中也設置document.domain,並且這也是必須的,雖然這個文檔的domain就是example.com,可是仍是必須顯示的設置document.domain的值:

<script>
document.domain = 'example.com'; // 也設置成主域
</script>

window.name

window對象有個name屬性,該屬性有個特徵:即在一個窗口(window)的生命週期內,窗口載入的全部的頁面都是共享一個window.name的,每一個頁面對window.name都有讀寫的權限,window.name是持久存在一個窗口載入過的全部頁面中的,並不會因新頁面的載入而進行重置。

window.name的值只能是字符串的形式。

好比有一個www.example.com/a.html頁面,須要經過a.html頁面裏的js來獲取另外一個位於不一樣域上的頁面www.cnblogs.com/data.html裏的數據。

data.html頁面裏的代碼很簡單,就是給當前的window.name設置一個a.html頁面想要獲得的數據值。data.html裏的代碼:

<script>
window.name = '我是頁面a.html須要的數據'
</script>

在a.html頁面中使用一個隱藏的iframe來充當一箇中間人角色,由iframe去獲取data.html的數據,而後a.html再去獲得iframe獲取到的數據。把這個iframe的src設爲www.cnblogs.com/data.html就好了。還必須把這個iframe的src設成跟a.html頁面同一個域才行,否則根據前面講的同源策略,a.html是不能訪問到iframe裏的window.name屬性的。這就是整個跨域過程。

<script>
function getData(){
    var iframe = document.getElementById('proxy')
    iframe.onload = function(){
        var data = iframe.contentWindow.name;
        alert(data)
    }
    iframe.src = 'b.html'
}
</script>

<iframe id="proxy" src="http://www.cnblogs.com/data.html" style="display:none;" onload="getData()"></iframe>

window.postMessage

是html5新引進的特性,可使用它來向其它的window對象發送消息,不管這個window對象是屬於同源或不一樣源。

調用postMessage方法的window對象是指要接收消息的那一個window對象,該方法的第一個參數message爲要發送的消息,類型只能爲字符串;第二個參數targetOrigin用來限定接收消息的那個window對象所在的域,若是不想限定域,可使用通配符 *  。

須要接收消息的window對象,但是經過監聽自身的message事件來獲取傳過來的消息,消息內容儲存在該事件對象的data屬性中。

//這是 頁面 http://test.com/a.html 中的代碼

<script>
function onLoad(){
    var iframe = document.getElementById('iframe')
    var win = iframe.contentWindow;//獲取window對象
    win.postMessage('我是來自a.html的消息')//向不一樣域頁面發送消息
}
</script>
<iframe id="iframe" src="http://www.test.com/b.html" onload="onLoad()"></iframe>
//這是 頁面http://www.test.com/b.html的代碼

<script>
window.onmessage = function(e){ //註冊message事件來接收消息
    e = e || event;//獲取事件對象
    alert(e.data)//經過data屬性獲得傳送的消息
}
</script>

後端修改header

header(‘Access-Control-Allow-Origin:*’);//容許全部來源訪問

header(‘Access-Control-Allow-Method:POST,GET’);//容許訪問的方式

 

nginx反向代理

Nginx配置

server{
    # 監聽9099端口
    listen 9099;
    # 域名是localhost
    server_name localhost;
    #凡是localhost:9099/api這個樣子的,都轉發到真正的服務端地址http://localhost:9871 
    location ^~ /api {
        proxy_pass http://localhost:9871;
    }    
}

網上更詳細的資源:https://segmentfault.com/a/1190000015597029

相關文章
相關標籤/搜索