經過postMessage進行跨域通訊

最近工做中遇到一個需求,場景是:將一個pc端a頁面做爲主要展現內容內嵌在另外一個pc端b頁面中,用戶在a頁面中點擊關閉的時候,而後b頁面也實現關閉的效果。算法

這裏首先想到就是經過iframe將a頁面內嵌到b頁面中,而後a頁面經過postMessage方法,把變化的數據發送給b頁面,b頁面經過addEventListener接收數據,進行關閉操做。chrome

postMessage()語法以及相關api說明

targetWindow.postMessage(message,targetOrigin,[ transfer ]);複製代碼

targetWindow

對將接收消息的窗口的引用。得到此類引用的方法包括:
  • window.open (生成一個新窗口而後引用它),
  • window.opener (引用產生這個的窗口),
  • HTMLIFrameElement.contentWindow<iframe>從其父窗口引用嵌入式,可簡單理解爲從父級頁面向本身頁面進行數據傳遞),
  • window.parent(從嵌入式內部引用父窗口<iframe>,可簡單理解爲從子級頁面向父級頁面傳遞數據)(當前場景下所用的window.parent
  • window.frames +索引值(命名或數字)。

message

要發送到其餘窗口的數據。使用結構化克隆算法序列化數據。這意味着能夠將各類各樣的數據對象安全地傳遞到目標窗口,而無需本身序列化。api

targetOrigin

指定要調度的事件的 targetWindow的原點,能夠是文字字符串 "*"(表示沒有首選項),也能夠是URI。若是在計劃調度事件時, targetWindow文檔的方案,主機名或端口與 targetOrigin提供的內容不匹配,則不會調度該事件;只有當全部的三個條件都匹配時,將調度該事件。該機制能夠控制發送消息的位置;例如,若是 postMessage()用於傳輸密碼,則該參數必須是URI,其來源與包含密碼的消息的預期接收者相同,以防止惡意第三方攔截密碼。始終提供具體的 targetOrigin,而不是 *,若是您知道其餘窗口的文檔應該位於何處。未能提供特定目標會泄露您發送給任何感興趣的惡意站點的數據。

transfer(可選的)

是與消息一塊兒傳輸的 Transferable 對象序列。這些對象的全部權將提供給目標端,而且它們在發送端再也不可用。

能夠經過執行如下JavaScript來偵聽已分派的消息:

window.addEventListener("message", msgHandler, false);
function msgHandler(event){
  if (event.origin !== "http://yourhost.com")    return;

  // ...
}複製代碼
相關屬性說明:
data

從另外一個窗口傳遞的對象。安全

originbash

調用當時發送消息的窗口的原點 postMessage 。此字符串是協議和「://」的串聯,若是存在,則爲主機名,若是存在端口,則「:」後跟端口號,而且與給定協議的默認端口不一樣。典型起源的例子是 https://example.org (意味着端口爲 443 ), http://example.net (意味着端口爲 80 )和 http://example.com:8080 。請注意,此來源
保證是該窗口的當前或將來來源,該窗口可能已被導航到調用 postMessage後的其餘位置。

sourceapp

對發送消息的 window對象的引用;你可使用它來創建兩個不一樣來源的窗口之間的雙向通訊。


問題解決:

那麼,在a頁面中,能夠經過下面代碼發送消息:

window.parent.postMessage('isClosed', 'http://yourhost.com');複製代碼

在b頁面中,經過下面代碼便可接收到消息:post

window.addEventListener('message', msgHandler, false);複製代碼


relevant  and important

安全問題部分ui

若是您不但願從其餘站點接收消息,請不要爲message事件添加任何事件偵聽器。這是避免安全問題的徹底萬無一失的方法。
spa

若是您確實但願從其餘站點接收消息,則請始終使用origin和可能的source屬性驗證發件人的身份。任何窗口(例如,包括http://evil.example.com)均可以向任何其餘窗口發送消息,而且您沒法保證未知發件人不會發送惡意消息。可是,在驗證了身份後,您仍應始終驗證收到的消息的語法。不然,您信任的站點中的安全漏洞只能發送受信任的消息,而後能夠在站點中打開跨站點腳本漏洞。.net

在postMessage用於將數據發送到其餘窗口時,始終指定精確的目標原點,而不是*。惡意站點能夠在您不知情的狀況下更改窗口的位置,所以它能夠攔截使用postMessage發送的數據。

在擴展中使用window.postMessage

window.postMessage可用於在chrome代碼中運行的JavaScript(例如,在擴展和特權代碼中),但調度事件的source屬性始終爲null,以此做爲安全限制。(其餘屬性具備預期值。)

內容或Web上下文腳本沒法指定targetOrigin直接與擴展(後臺腳本或內容腳本)通訊。Web或內容的腳本可使用帶有"*"的targetOrigin的window.postMessage與來廣播到每個偵聽器,可是不鼓勵這樣作,由於擴展不能肯定這樣的消息,和其餘偵聽器(包括那些你不控制的偵聽器)能夠偵聽。

內容腳本應使用runtime.sendMessage與後臺腳本進行通訊。Web上下文腳本可使用自定義事件與內容腳本進行通訊(若是須要,能夠隨機生成事件名稱,以防止從客戶頁面進行窺探)。

最後,將消息發佈到file:URL處的頁面,當前要求targetOrigin參數爲"*"。file://不能用做安全限制;此限制可能會在未來修改。

相關文章
相關標籤/搜索