跨域是指 從一個域名的網頁去訪問另外一個域名的資源,只要協議、域名、端口有任何一個不一樣,就被看成是跨域。javascript
這是有瀏覽器的 同源策略 形成的。所謂同源是指, 域名、協議、端口均相同。html
同源策略限制一下幾種行爲:html5
一、Cookie、LocalStorage 和 IndexDB(瀏覽器本地數據庫) 沒法讀取;java
二、DOM 和 JS對象沒法獲取;node
三、AJAX 請求不能發送nginx
緣由在於同源策略 是用來隔離潛在惡意文件的關鍵機制。若是缺乏了同源策略,瀏覽器很容易受到XSS(跨域腳本攻擊)和 CSRF(跨站請求僞造)的攻擊。數據庫
一、 經過jsonp跨域
二、 document.domain + iframe跨域
三、 location.hash + iframe
四、 window.name + iframe跨域
五、 postMessage跨域
六、 跨域資源共享(CORS)
七、 nginx代理跨域
八、 nodejs中間件代理跨域
九、 WebSocket協議跨域json
原理:經過script標籤引入一個js文件,這個js文件載入成功後會執行咱們在url參數中指定的函數,而且會把咱們須要的json數據做爲參數傳入(即用 Javascript 動態script,再請求一個帶參網址實現跨域通訊)。segmentfault
<script> var script = document.createElement('script'); script.type = 'text/javascript'; // 傳參並指定回調執行函數爲onBack script.src = 'http://www.domain2.com:8080/login?user=admin&callback=onBack'; document.head.appendChild(script); // 回調執行函數 function onBack(res) { alert(JSON.stringify(res)); } </script>
服務端返回數據:跨域
onBack({"status": true, "user": "admin"})
JSONP的優缺點:
優勢:
一、它不像XMLHttpRequest
對象實現的Ajax請求那樣受到同源策略的限制;
二、它的兼容性更好,在更加古老的瀏覽器中均可以運行,不須要XMLHttpRequest或ActiveX的支持;
三、而且在請求完畢後能夠經過調用callback的方式回傳結果。
缺點:
一、只能實現 GET 一種請求;
二、只支持跨域HTTP請求這種狀況。
經過src屬性,img能夠引用其它站點或圖牀的圖片,大大下降本站的圖片持久。
經過src屬性,script能夠引用CDN的JS文件,加速了瀏覽器的腳本文件的下載,跨域的數據獲取更加高效和方便。
經過src屬性,iframe能夠嵌入其它站點的頁面,可讓頁面的框架和可變內容分離,內容引用較爲靈活,方便引用其它站點。
不一樣的是:
使用 img標籤 不能訪問服務器返回的響應內容,只能單向的發送get請求。
使用 script標籤 實現的jsonp跨域能夠將服務器響應文本以函數參數的形式返回。
CORS 的基本思想就是使用自定義的 HTTP 頭部 讓瀏覽器與服務器進行溝通,決定請求或響應式是成功仍是失敗。
服務器對於CORS的支持,主要是經過設置 Access-Control-Allow-Origin 來進行的,若是瀏覽器檢測到響應的設置,就容許 AJAX 進行跨域訪問。
只須要在後臺中加上響應頭來容許域請求,在被請求的Response header中加入如下設置,就能夠實現跨域訪問。
//指定容許其餘域名訪問 'Access-Control-Allow-Origin:*'//或指定域 //響應類型 'Access-Control-Allow-Methods:GET,POST' //響應頭設置 'Access-Control-Allow-Headers:x-requested-with,content-type'
postMessage是HTML5 XMLHttpRequest Level 2中的API,且是爲數很少能夠跨域操做的window屬性之一,它可用於解決如下方面的問題:
一、 頁面和其打開的新窗口的數據傳遞
二、 多窗口之間消息傳遞
三、 頁面與嵌套的iframe消息傳遞
四、上面三個場景的跨域數據傳遞
用法:postMessage(data,origin)方法接受兩個參數
data: html5規範支持任意基本類型或可複製的對象,但部分瀏覽器只支持字符串,因此傳參時最好用JSON.stringify()序列化。
origin: 協議+主機+端口號,也能夠設置爲"*",表示能夠傳遞給任意窗口,若是要指定和當前窗口同源的話設置爲"/"。
(1)a.html(http://www.domain1.com/a.html)
<iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe> <script> var iframe = document.getElementById('iframe'); iframe.onload = function() { var data = { name: 'aym' }; // 向domain2傳送跨域數據 iframe.contentWindow.postMessage(JSON.stringify(data), 'http://www.domain2.com'); }; // 接受domain2返回數據 window.addEventListener('message', function(e) { alert('data from domain2 ---> ' + e.data); }, false); </script>
(2)、b.html(http://www.domain2.com/b.html)
<script> // 接收domain1的數據 window.addEventListener('message', function(e) { alert('data from domain1 ---> ' + e.data); var data = JSON.parse(e.data); if (data) { data.number = 16; // 處理後再發回domain1 window.parent.postMessage(JSON.stringify(data), 'http://www.domain1.com'); } }, false); </script>