1. 程式人生 > 實用技巧 >HTML5 之跨域通訊(postMessage)

HTML5 之跨域通訊(postMessage)

很多情況下,我們受到瀏覽器的安全策略限制。如何能規避此限制,並且能安全的使用跨域通訊,這就不得不介紹一下 postMessage 了。

一、關於 postMessage

window.postMessage() 方法可以安全地實現跨源通訊。

通常,對於兩個不同頁面的指令碼,只有當執行它們的頁面位於具有相同的協議(通常為https),埠號(443為https的預設值),以及主機 (兩個頁面的模數Document.domain設定為相同的值) 時,這兩個指令碼才能相互通訊。

window.postMessage()方法提供了一種受控機制來規避此限制,只要正確的使用,這種方法就很安全。

二、理解過程

window.postMessage()方法被呼叫時,會在所有頁面指令碼執行完畢之後向目標視窗派發一個MessageEvent訊息。 該MessageEvent訊息有四個屬性:

1.message屬性表示該message的型別;

2.data屬性為window.postMessage的第一個引數;

3.origin屬性表示呼叫window.postMessage()方法時呼叫頁面的當前狀態;

4.source屬性記錄呼叫window.postMessage()方法的視窗資訊。

三、相容性

通過上面的圖片,我們可以看出來,幾乎所有的瀏覽器都支援了postMessage,所以放心大膽的去使用吧。

四、用法簡介

基本用例:

otherWindow.postMessage(message, targetOrigin, [transfer]);

1.otherWindow
其他視窗的一個引用,比如iframe的contentWindow屬性、執行window.open返回的視窗物件、或者是命名過或數值索引的window.frames。

2.message
將要傳送到其他window的資料。它將會被結構化克隆演算法序列化。

這意味著我們可以不受什麼限制的將資料物件安全的傳送給目標視窗而無需自己序列化。

3.targetOrigin
通過視窗的origin屬性來指定哪些視窗能接收到訊息事件,其值可以是字串 「*」(表示無限制)或者一個URI。

在傳送訊息的時候,如果目標視窗的協議、主機地址或埠這三者的任意一項不匹配targetOrigin提供的值,那麼訊息就不會被髮送;

只有三者完全匹配,訊息才會被髮送。這個機制用來控制訊息可以傳送到哪些視窗。

我們舉個例子,當用postMessage傳送密碼時,這個引數就顯得尤為重要,必須保證它的值與這條包含密碼的資訊的預期接受者的origin屬性完全一致,來防止密碼被惡意的第三方截獲。

如果你明確的知道訊息應該傳送到哪個視窗,那麼請始終提供一個有確切值的targetOrigin,而不是*。

需要注意:不提供確切的目標將導致資料洩露到惡意站點。

4.transfer
是一串和message同時傳遞的Transferable物件. 這些物件的所有權將被轉移給訊息的接收方,而傳送一方將不再保有所有權。

五、事件監聽

我們來看下面這段程式碼:

window.addEventListener("message", receiveMessage, false);
function receiveMessage(event)
{
  // For Chrome, the origin property is in the event.originalEvent
  // object. 
  // 這裡不準確,chrome沒有這個屬性
  // var origin = event.origin || event.originalEvent.origin; 
  var origin = event.origin
  if (origin !== "http://jartto.wang:8080")
    return;
  // ...
}

1.data
從其他window中傳遞過來的物件。

2.origin
呼叫postMessage時訊息傳送方視窗的origin. 這個字串由 協議、://、域名、: 埠號拼接而成。

例如https://jartto.wang (隱含埠 443)、http://jartto.net(隱含埠 80)、http://jartto.com:8080。請注意,這個origin不能保證是該視窗的當前或未來origin,因為postMessage被呼叫後可能被導航到不同的位置。

3.source
對傳送訊息的視窗物件的引用, 我們可以使用此來在具有不同origin的兩個視窗之間建立雙向通訊。

資源搜尋網站大全 https://www.renrenfan.com.cn

六、簡單應用

1.監聽message事件:

window.addEventListener("message", receiveMessage, false);

function receiveMessage(event)
{
  console.log('get it !!!',event);
}

2.傳送資料

window.postMessage({
    name: 'Jartto',
    say: 'hello~',
    arr: [1,2,3]
}, '*');