跨域技術(上下完整版)

跨域技術(上)

跨域技術(上)包括 同源策略及其限制什麼是跨域圖像PingJSONPCORSWebSocket 等跨域技術。php

(一)同源策略及其限制

同源策略

點擊查看瀏覽器同源策略官方又臭又長說法html

同源策略限制內容

  • Cookie、LocalStorage、IndexedDB 等存儲性內容
  • DOM 節點獲取
  • AJAX 請求的發送

(二)什麼是跨域

所謂同源是指:協議,域名,端口都相同,就是同源;前端

協議,域名,端口號有一個不一樣就是跨域nginx

跨域並非請求發不出去,請求能發出去,服務端能收到請求並正常返回結果,只是結果被瀏覽器攔截了。 git

可能嵌入跨源的資源的標籤

<script src="..."></script> | 標籤嵌入跨域腳本。github

<link rel="stylesheet" href="..."> | 標籤嵌入CSS。web

<img> | 嵌入圖片。支持的圖片格式包括PNG,JPEG,GIF,BMP,SVG,...ajax

<video><audio> | 嵌入多媒體資源。json

<object>, <embed><applet> 的插件。segmentfault

<frame><iframe> | 載入的任何資源。站點可使用X-Frame-Options消息頭來阻止這種形式的跨域交互。

@font-face 引入的字體 | 一些瀏覽器容許跨域字體(cross-origin fonts),一些須要同源字體(same-origin fonts)。

background: url(); 背景連接 | 嵌入的資源可能存在跨域

可能存在跨源的場景

  • 資源跳轉: A連接跳轉、重定向、表單提交
  • 資源嵌入: <link><script><img><frame>等dom標籤
  • 腳本請求: ajax請求、dom和js對象的跨域操做等

(三)幾種跨域技術的討論

圖像Ping

1.原理

  • 咱們知道,一個網頁能夠從任何網頁中加載圖像,不用擔憂跨域不跨域。這也是在線廣告跟蹤瀏覽量的主要方式。
  • 能夠動態地建立圖像,使用它們的onloadonerror 事件處理程序來肯定是否接收到了響應。
  • 動態建立圖像常常用於圖像 Ping。圖像 Ping 是與服務器進行簡單、單向的跨域通訊的一種方式。

2.具體步驟

請求的數據是經過查詢字符串形式發送的,而響應能夠是任意內容,但一般是像素圖或 204 響應。經過圖像 Ping,瀏覽器得不到任何具體的數據,但經過偵聽 load 和 error 事件,它能知道響應是何時接收到的。

let img = new Image(); //建立了一個 Image 的實例
// 將 onload 和 onerror 事件處理程序指定爲同一個函數
img.onload = img.onerror = function(){ 
    alert("Done!"); 
}; 
// 請求中發送了一個 name 參數
img.src = "http://www.example.com/test?name=Nicholas";
複製代碼

3.應用場景

圖像 Ping 最經常使用於跟蹤用戶點擊頁面或動態廣告曝光次數。

4.圖像 Ping 的缺點

  • 一是隻能發送 GET 請求,
  • 二是沒法訪問服務器的響應文本。所以,圖像 Ping 只能用於瀏覽器與服務器間的單向通訊。

JSONP(JSON with padding 填充式JSON)

1.JSONP的做用、組成

  • JSONP可以讓網頁從別的地址(跨域的地址)那獲取資料,即跨域讀取數據
  • JSONP 由兩部分組成:回調函數和數據。
    • 回調函數是當響應到來時應該在頁面中調用的函數。回調函數的名字通常是在請求中指定的。
    • 而數據就是傳入回調函數中的JSON數據。

2.JSONP實現跨域訪問的原理及優化

2.1 <script>標籤的做用

  • 在同一界面中能夠定義多個<script>標籤,同一個界面中多個<script>標籤中的數據能夠相互訪問
  • 能夠經過<script>的src屬性導入其它資源,經過src屬性導入其它資源的本質就是將資源拷貝到<script>標籤中
  • <script>的src屬性不只能導入本地資源, 還能導入遠程資源
  • 因爲<script>的src屬性沒有同源限制, 因此能夠經過<script>的src屬性來請求跨域數據

2.2 JSONP原理

JSONP 是經過動態<script>元素來使用的,使用時能夠爲 src 屬性指定一個跨域 URL。這裏的<script>元素與<img>元素相似,都有能力不受限制地從其餘域加載資源。由於 JSONP 是有效的 JavaScript代碼,因此在請求完成後,即在 JSONP 響應加載到頁面中之後,就會當即執行。

2.3 JSONP優化

2.3.1 爲何要優化(存在的問題)?

  • 經過JSONP來獲取跨域的數據,通常狀況下服務器返回的都不會是一個變量,而是一個函數的調用
  • 當前服務器返回的函數調用名稱若是是固定的,服務器返回函數叫什麼名稱,咱們本地就必須定義一個叫什麼名稱的函數
  • 因爲<script>標籤默認是同步,前面的<script>標籤沒有加載完數據,後面的<script>標籤就不會被執行, 因此請求數據的<script>標籤必須放到後面

2.3.2 解決方案:

  • 經過URL參數的方式來動態指定函數名稱
  • 經過JS動態建立<script>標籤,由於JS動態建立的<script>標籤默認就是異步的, 不用等到前面的標籤加載完就能夠執行後面的<script>標籤

2.3.3 實現方式

原生實現

<script>
    //jsonp回調方法,必定要寫在jsonp請求前面
    function testjson(txt){
    	alert(txt);
    }
</script>

<script>
    //動態建立<script>標籤
    let oScript = document.createElement("script");
    oScript.src = "http://127.0.0.1:80/jQuery/Ajax/20-jsonp.php?cb=test";
    document.body.appendChild(oScript);
</script>
複製代碼

jQuery方式實現

jQuery中的Ajax能夠設置爲請求跨域的數據

  • dataType: "jsonp" | 設置請求方式爲jsonp,告訴jQuery須要請求跨域的數據。
  • jsonp: "cb" | 告訴jQuery服務器在獲取回調函數名稱的時候須要用什麼key來獲取
  • jsonpCallback: "handleCallback" | 自定義回調函數名,告訴jQuery服務器在獲取回調函數名稱的時候回調函數的名稱是什麼
<script>
    $.ajax({
        url: "http://127.0.0.1:80/jQuery/Ajax/22-jsonp.php",
        data:{
            "name": "ghk",
            "age": 18
        },
        dataType: "jsonp",   // 設置請求方式爲jsonp
        jsonp: "cb",  
        jsonpCallback: "handleCallback", // 自定義回調函數名
        success: function (msg) {
            console.log(msg);
        }
    });
</script>
複製代碼

3.JSONP的優缺點

3.1 優勢

與圖像 Ping 相比,它的優勢在於可以直接訪問響應文本,支持在瀏覽器與服務器之間雙向通訊。

3.2 缺點

  • JSONP 是從其餘域中加載代碼執行。若是其餘域不安全,極可能會在響應中夾帶一些惡意代碼,而此時除了徹底放棄 JSONP 調用以外,沒有辦法追究。
  • 不能註冊success、error等事件的監聽,因此要肯定 JSONP 請求是否失敗並不容易
  • JSONP 只支持get請求(JSONP的實現原理就是建立一個script標籤,再把須要請求的api地址放到src裏. 因此只能是get請求.)

CORS (Cross-origin resource sharing 跨域資源共享)

1.CORS是什麼及原理

誰應該讀這篇文章? 說實話,每一個人。

一句話總結:CORS是跨域的根本解決方法(處理跨域問題的標準作法),由瀏覽器自動完成。

CORS是一個W3C標準,它容許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。

CORS背後的基本思想:使用自定義的HTTP頭部讓瀏覽器與服務器進行溝通,從而決定請求或響應是應該成功,仍是應該失敗。

整個CORS通訊過程,都是瀏覽器自動完成,不須要用戶參與。對於開發者來講,CORS通訊與同源的AJAX通訊沒有差異,代碼徹底同樣。瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感受。

所以,實現CORS通訊的關鍵是服務器。只要服務器實現了CORS接口,就能夠跨源通訊。

2.CORS的兩種請求

瀏覽器將CORS請求分紅兩類:簡單請求(simple request)和非簡單請求(not-so-simple request)。

只要同時知足如下兩大條件,就屬於簡單請求。

(1) 請求方法是如下三種方法之一:

  • HEAD
  • GET
  • POST

(2) HTTP的頭信息不超出如下幾種字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain

凡是不一樣時知足上面兩個條件,就屬於非簡單請求。

瀏覽器對這兩種請求的處理,是不同的。(阮老師這裏有對這兩種請求的詳細解說)

3.實現

普通跨域請求:服務端設置Access-Control-Allow-Origin便可,前端無須設置;若要帶cookie請求,先後端都須要設置。

在響應頭上添加 Access-Control-Allow-Origin 屬性,指定同源策略的地址。同源策略默認地址是網頁的自己。只要瀏覽器檢測到響應頭帶上了CORS,而且容許的源包括了本網站,那麼就不會攔截請求響應。

原生實現

let xhr = new XMLHttpRequest();
xhr.withCredentials = true;// 前端設置是否帶cookie
...
複製代碼

jQuery Ajax

$.ajax({
    ...
    xhrFields: {
        withCredentials: true,  // 前端設置是否帶cookie
    },
    crossDomain: true, // 會讓請求頭中包含跨域的額外信息,但不會含cookie
    ...
});
複製代碼

4.CORS優缺點

CORS要求瀏覽器(>IE10)和服務器的同時支持,是跨域的根本解決方法,由瀏覽器自動完成。 優勢在於功能更增強大支持各類HTTP Method,缺點是兼容性不如JSONP。

WebSocket

同源策略對 WebSocket 不適用,所以能夠經過它打開到任何站點的鏈接。

1.WebSocket的由來

爲了解決服務器向瀏覽器端及時推送消息的需求,提出了一些替代的、變通的解決方案,如iframe、AJAX,基本思路是瀏覽器端及時提交請求,服務器收到請求後進行阻塞,並保持鏈接,等待有消息須要發送時,及時向瀏覽器端進行響應推送。 然而,這些技術都是基於HTTP協議實現。從根本上講,HTTP是半雙工的協議,也就是說,在同一時刻信息只能單向傳輸。瀏覽器端向服務器發送請求(單向),而後服務器響應請求(單向)。這樣,服務器只能被動的接收到請求信息後,再向瀏覽器端響應請求,而沒法主動向客戶端推送信息。

然而,隨着人們對信息的實時性要求愈來愈高(如在線訂票系統、即時通訊系統和股票交易系統等),當服務器數據發生變化的時候,須要主動、實時地向瀏覽器端發送消息,將最新的數據或事件通知給用戶。顯然,HTTP做爲半雙工的通訊協議並不能高效地支持上述需求功能的實現。咱們須要一種高效節能的全雙工通訊機制來保證數據的實時傳輸。所以,WebSocket應運而生。

2.WebSocket的優勢和應用場景

2.1 WebSocket的優勢

WebSocket做爲一種高效的全雙工通訊機制,有以下優勢

  • WebSocket經過一個單一的套接字在Web上進行操做,以最小的開銷高效地提供了Web鏈接。相較於常常須要使用推送實時數據到瀏覽器端的輪詢、長輪詢及長鏈接來講,這就極大地減小了沒必要要的網絡流量
  • 實現了瀏覽器與服務器的雙向通道服務器和瀏覽器端能夠主動的發送數據給對方
  • WebSocket減小了延遲,由於一旦創建起WebSocket鏈接,服務器能夠在消息可用時發送它們,不用頻繁建立TCP請求及銷燬請求,減小網絡帶寬資源的佔用,同時也節省服務器資源。
  • WebSocket減小了網絡帶寬資源的佔用,由於無需頻繁建立及銷燬
  • WebSocket節省了服務器資源。由於一旦創建起WebSocket鏈接,服務器能夠在後臺數據更新時及時推送消息給客戶端。

2.2 應用場景

經過WebSocket實現的瀏覽器後臺傳輸技術,能夠應用於如多媒體聊天、實時狀態監控、股票行情、基於位置的應用等須要實時刷新的應用場景。

3.WebSocket協議通訊機制

WebSocket協議是獨立的、基於TCP的協議。其本質是先經過HTTP/HTTPS協議進行握手後建立一個用於交換數據的TCP鏈接,此後服務器端與瀏覽器端經過此TCP鏈接進行實時通訊。

圖所示爲WebSocket的通訊模式:

瀏覽器端首先向服務器端發起一個HTTP請求。這個請求包含了一些附加頭信息,是一個升級的HTTP請求。服務器端解析這些附加頭信息後,產生應答信息返回給瀏覽器端。這樣,瀏覽器端和服務器端之間的WebSocket鏈接就創建起來了。雙方能夠經過這個鏈接通道自由地傳輸數據,直到瀏覽器端或服務器端主動關閉該鏈接。

4.WebSocket協議通訊實現的相關技術

4.1 WebSocket構造函數

4.1.1 客戶端要和服務器端創建WebSocket鏈接,只需使用構造函數創建一個WebSocket對象,而且爲這個對象提供鏈接端口的URL地址便可。

let  ws = new  WebSocket("ws://127.0.0.1:8080/WebSocket/WebSocket")
複製代碼

4.1.2 注意點

  • URL地址的字符串須要以「ws」或「wss」(加密通訊時使用)做爲開頭。若是URL地址有語法錯誤,那麼構造函數將會拋出異常。

  • 必須給 WebSocket 構造函數傳入絕對 URL。同源策略對 Web Sockets 不適用,所以能夠經過它打開到任何站點的鏈接。至因而否會與某個域中的頁面通訊,則徹底取決於服務器。

4.2 WebSocket的readyState屬性

readyState 屬性返回實例對象的當前狀態,共有四種。

狀態 含義
WebSocket.OPENING (0) 正在創建鏈接。
WebSocket.OPEN (1) 已經創建鏈接。
WebSocket.CLOSING (2) 正在關閉鏈接。
WebSocket.CLOSE (3) 已經關閉鏈接。

4.3 WebSocket事件

  • open 事件(WebSocket鏈接創建後觸發該事件)
    一旦服務器響應了客戶端的WebSocket鏈接請求,open事件就會被觸發。而要監聽open事件,只須要爲其添加回調函數。

    ws.onopen = function(){
        setConnected(true));
    };
    複製代碼
  • message 事件(當客戶端接收到服務器的數據時觸發該事件)
    當客戶端接收到服務器發送的消息後,message事件觸發,而且客戶端可調用相應函數對所接收的消息進行處理。

    ws.onmessage= function(e){
        console.log("接收:"+e.data);
    }
    複製代碼
  • error 事件(當通訊過程當中發生錯誤時觸發該事件)
    error事件會在WebSocket鏈接出現故障時觸發,用來處理異常事件。

    ws.onerror = function(e){
        console.log("WebSocket Error: ", e);
    };
    複製代碼
  • close 事件(當鏈接關閉時觸發該事件)。
    若是接收到error事件,能夠預期很快會觸發close事件。close事件在WebSocket鏈接關閉時觸發,處理程序以下所示:

    ws.onclose = function(e){
        setConnected(false));
    };
    複製代碼

    一旦鏈接關閉,客戶端和服務器再也不接收或者發送消息。

4.4 WebSocket方法

WebSocket對象有兩個方法即send()和close(),分別用來發送數據和關閉鏈接。

  • send() 方法
    WebSocket在客戶端和服務器之間創建鏈接後,就能夠調用send()方法來傳輸數據,語法格式以下所示:
    ws.send("message");
    複製代碼
  • close() 方法
    使用close()方法,能夠關閉WebSocket鏈接,語法格式以下所示:
    ws.close(code, reason);
    複製代碼
    能夠在close()方法傳遞兩個可選參數:code(數字型的狀態代碼)和reason(一個文本字符串),用來講明關閉鏈接的緣由。

5.WebSocket小結

有沒有發現好用的東西、牛逼的東西總得要有點小缺陷才行,例如兼容問題,否則開發就沒啥意思了(不是

JavaScript 中建立了 WebSocket 以後,會有一個 HTTP 請求發送到瀏覽器以發起鏈接。在取得服務器響應後,創建的鏈接會使用 HTTP 升級從 HTTP 協議交換爲 Web Socket 協議。

也就是說,使用標準的 HTTP 服務器沒法實現 WebSocket ,只有支持這種協議的專門服務器才能正常工做

目前支持WebSocket的服務器有不少,包括了Jetty七、Netty、mod pyWebSocket、Nodejs和Tomcat7等。在雙向通道創建後,服務器端一樣採用事件驅動的架構模式,監聽事件、並觸發相應方法函數來向客戶端推送數據。


本文參考書籍:

《JavaScript高級程序設計》

本文參考連接:

瀏覽器的同源策略 MDN

HTTP訪問控制(CORS) MDN

跨域資源共享 CORS 詳解 阮一峯

WebSocket 教程 阮一峯

不要再問我跨域的問題了



跨域技術(下)

跨域技術(下)包括 iframe標籤的使用document.domainwindow.namelocation.hashpostMessage等跨域技術。

iframe標籤

域名地址的組成

iframe 標籤

iframe是一種HTML標記,它會建立包含另一個文檔的內聯框架,經過iframe框架能夠在當前頁面中顯示其餘頁面的信息。

將iframe的src屬性設置爲對另一個頁面的鏈接請求,並在當前頁面中經過JavaScript動態更新iframe的內容,就能夠將服務器端的數據響應到客戶端且而不會出現主頁面一片空白,等待刷新的現象。

而且,僅刷新iframe框架而不是主頁面,也減小了頁面刷新的內容,這在必定程度上提升了頁面刷新速度。

iframe 標籤的使用

1.用iframe嵌套頁面時,若是父頁面要獲取子頁面裏面的內容,可使用 contentWindow 或者contentDocument

子頁面獲取父頁面使用window.parent

//父窗口
<iframe id="father" src="iframe.html"></iframe>
<script>
    console.log(iframe.contentWindow); //獲取子頁面裏面的內容
    console.log(iframe.contentDocument);
</script>

//子窗口
<div id="son">內容</div>
<script>
  console.log(window.parent); //獲取父頁面內容
</script>
複製代碼

2.頁面間通訊,獲取子頁面的內容、cookie等

//父窗口
<iframe id="father" src="iframe.html"></iframe>
<script>
  let iframe = document.getElementById("father");
  iframe.onload = function(){
    let doc = iframe.contentWindow.document;
    console.log(doc.getElementById('son').innerHTML);//'內容'
    console.log(document.cookie);//'name=match'
  }
</script>

//子窗口
<div id="son">內容</div>
<script>
  document.cookie = 'name=match';
</script>
複製代碼

document.domain + iframe(主域相同的跨域)

這種方式只適合主域名相同,子域名不一樣的iframe跨域

經過修改document的domain屬性,咱們能夠在域和子域或者不一樣的子域之間通訊。同域策略認爲域和子域隸屬於不一樣的域,好比www.a.com和sub.a.com是不一樣的域,這時,咱們沒法在www.a.com下的頁面中調用sub.a.com中定義的JavaScript方法。可是當咱們把它們document的domain屬性都修改成a.com,瀏覽器就會認爲它們處於同一個域下,那麼咱們就能夠互相調用對方的method來通訊了。

document.domain實現跨域核心

1.主域相同而二級域名不一樣的狀況下,兩個文件分別加上 document.domain = "example.com";而後經過 a.html 文件建立一個 iframe,去控制 iframe 的 window,從而進行交互,這種方法只能解決主域相同而二級域名不一樣的狀況。

2.注意

使用document.domain容許子域安全訪問其父域時,您須要設置document域在父域和子域中具備相同的值。這是必要的,即便這樣作只是將父域設置回其原始值。不然可能會致使權限錯誤。這裏都是a.com。

// 在www.a.com/a.html中:
<script>
    document.domain = 'a.com';
    let ifr = document.createElement('iframe');
    ifr.src =  'http://www.script.a.com/b.html';  
    ifr.display = none;
    document.body.appendChild(ifr);
    ifr.onload = function(){ 
        let doc = ifr.contentDocument || ifr.contentWindow.document;  
        ifr.onload = null;
};
</script>
複製代碼
// 在www.script.a.com/b.html中:
<script>
    document.domain ='a.com';
    window.data = '傳送的數據:1111';
</script>
複製代碼

window.name + iframe

window.name 屬性用於獲取/設置窗口的名稱。該屬性有個特徵:即在一個窗口(window)的生命週期內,窗口載入的全部的頁面都是共享一個window.name的,每一個頁面對window.name都有讀寫的權限,window.name是持久存在一個窗口載入過的全部頁面中的。window.name屬性的神奇之處在於name值在不一樣的頁面(甚至不一樣域名)加載後依舊存在(若是沒修改則值不會變化),而且能夠支持很是長的 name 值(2MB)。

當該window的location變化,而後從新加載,它的name屬性能夠依然保持不變。

在控制檯輸入:

頁面跳轉到百度時,name屬性值不變

window.name實現跨域核心

能夠將跨域請求用以下步驟解決:

  • 在 a.github.io/a.html 中建立 iframe 指向 b.github.io/b.html (頁面會將自身的 window.name 附在 iframe 上)
  • 給 a.github.io/a.html 添加監聽 iframe 的 onload 事件,在該事件中將 iframe 的 src 設置爲本地域的代理文件(代理文件和a.html處於同一域下,能夠相互通訊),同時能夠傳出 iframe 的 name 值
  • 獲取數據後銷燬 iframe,釋放內存,同時也保證了安全

window.name 的優點在於巧妙地繞過了瀏覽器的跨域訪問限制,但同時它又是安全操做。

location.hash + iframe

location.hash就是錨點值,又稱爲片斷標識符(fragment identifier),指的是URL的#號後面的部分。

若是隻是改變片斷標識符,頁面不會從新刷新 ,因此能夠利用hash值來進行數據的傳遞,固然數據量是有限的。

location.hash實現跨域核心

1.假設 github.io 域名下 a.html 和 mouyuming.eu 域名下 b.html 存在跨域請求,那麼利用 location.hash 的一個解決方案以下:

  • a.html 頁面中建立一個隱藏的 iframe, src 指向 b.html,其中 src 中能夠經過 hash 傳入參數給 b.html
  • b.html 頁面在處理完傳入的 hash 後經過修改 a.html 的 hash 值達到將數據傳送給 a.html 的目的
  • a.html 頁面添加一個定時器,每隔必定時間判斷自身的 location.hash 是否變化,以此響應處理

以上步驟中須要注意第二點:如何在 iframe 頁面中修改 父親頁面的 hash 值。因爲在 IE 和 Chrome 下,兩個不一樣域的頁面是不容許 parent.location.hash 這樣賦值的,因此對於這種狀況,咱們須要在父親頁面域名下添加另外一個頁面來實現跨域請求,具體以下:

  • 假設 a.html 中 iframe 引入了 b.html, 數據須要在這兩個頁面之間傳遞,且 c.html 是一個與 a.html 同源的頁面
  • a.html 經過 iframe 將數據經過 hash 傳給 b.html
  • b.html 經過 iframe 將數據經過 hash 傳給 c.html
  • c.html 經過 parent.parent.location.hash 設置 a.html 的 hash 達到傳遞數據的目的

2.location.bash 方法的優缺點

優勢在於能夠解決域名徹底不一樣的跨域請求,而且能夠實現雙向通信

而缺點則包括如下幾點:

  • 利用這種方法傳遞的數據量受到 url 大小的限制,傳遞數據類型有限
  • 因爲數據直接暴露在 url 中則存在安全問題
  • 若瀏覽器不支持 onhashchange 事件,則須要經過輪訓來獲知 url 的變化
  • 有些瀏覽器會在 hash 變化時產生歷史記錄,所以可能影響用戶體驗

window.postMessage

HTML5 爲了跨域問題,引入了一個全新的 API:跨文檔通訊 API(Cross-document messaging)。這個 API 爲 window 對象新增了一個 window.postMessage 方法,容許跨窗口通訊,不論這兩個窗口是否同源。

詳細方法見MDN

圖所示爲postMessage的兼容性:

1.語法

  • 格式:otherWindow.postMessage(message, targetOrigin, [transfer]);

  • 參數:
    otherWindow | 其餘窗口的一個引用,好比iframe的contentWindow屬性、執行window.open返回的窗口對象、或者是命名過或數值索引的window.frames。

    message | 將要發送到其餘 window的數據;是具體的信息內容。

    targetOrigin | 接收消息的窗口的源(origin),即"協議 + 域名 + 端口"。也能夠設爲*,表示不限制域名,向全部窗口發送。

若是你明確的知道消息應該發送到哪一個窗口,那麼請始終提供一個有確切值的targetOrigin,而不是*。不提供確切的目標將致使數據泄露到任何對數據感興趣的惡意站點。

2.父窗口和子窗口均可以經過message事件,監聽對方的消息。

message 的屬性有:

data | 從其餘 window 中傳遞過來的對象。(消息內容)

origin | 調用 postMessage 時消息發送方窗口的 origin。(消息發向的網址)

source | 對發送消息的窗口對象的引用。(發送消息的窗口)

//發送頁面
<body>
<iframe id="myIframe" src="http://localhost:3000/user/reg"></iframe>
<input type="button" value="點我" onclick="test()">
<script>
   function test() {
      let frm = document.getElementById("myIframe");
      frm.contentWindow.postMessage("跨域請求信息","http://localhost:3000");
    }
</script>
</body>

// 接收頁面
<script>
    //接收信息頁面 http://localhost:3000/parent.html
    window.addEventListener("message",function (e) {
       console.log(e.data);
    },false);
</script>
複製代碼

其餘方式跨域

NodeJS中間件代理跨域、nginx反向代理中設置、flash等第三方插件等

等我會了這幾個再填這三種方式的坑

本文參考連接

iFrame跨域的方式

跨域資源共享的10種方式

前端跨域的幾種方式(超詳細,值得收藏)

window.postMessage MDN

相關文章
相關標籤/搜索