用postMessage實現跨域通訊
出於要打造一個各個web應用間能夠相互聯絡的生態系統的目標,則需要一種在各個視窗間安全傳送訊息的方式,利用postMessage()開發正是這樣一種方式。
曾經很長一段時間以來,只有遵守相同協議,並且具有相同埠號,同時在一個主機這樣的條件下,視窗間才能互發訊息。postMessage()提供了一種安全的跨域通訊方法,從而打破了這樣的限制。
在這篇文章中你將首先學習如何利用postMessage()實現分別處在不同域下的兩個視窗之間的通訊,其中一個視窗是控制視窗(controller window),另一個是接收視窗(receiver window )。
postMessage()接收兩個引數:
1、 message——即將被髮送到接收視窗的字串或者物件。
2、targetOrigin ——接收視窗的URL。為能實現訊息的成功傳送,目標視窗的協議名,埠號以及主機名必須匹配。“*”能夠匹配任何URL,為安全考慮,我們不鼓勵這麼做。
如果一個視窗(控制視窗)想向其他視窗(接收視窗)傳送訊息,則控制視窗可以呼叫這個方法。我們可以用多種不同方法獲得目標視窗的引用。
1、 使用window.open()方法將返回一個新視窗的引用;
2、 對iframes而言,可以使用iframes的contentWindow屬性。
targetWindow.postMessage('Hello World!', 'http://example.com');
下面讓我們來研究下如何在接收視窗上接收資訊。
新增事件監聽器來接收訊息
傳入監聽器回撥的事件有項屬性data,能夠用來獲取由postMessage傳入的string或者object。
window.addEventListener('message', function(e) {
var message = e.data;
});
示例:與iframe通訊
使用postMessage與iframe進行通訊
現在你已經掌握瞭如何使用postMessage()在不同視窗間傳遞訊息,下面讓我來看一個例子。
在這個部分我們將在程式碼層面講述通過一個示例演示控制頁面如何與利用iframe巢狀在其中的接收頁面進行通訊的。
控制視窗
首先我們需要為控制頁面寫一些html,其中的主要元素有一個是<button>,用來傳送訊息。另外一個是個<iframe>,用來展示巢狀的接收頁面(釋出在另外一個域上)。
<h1>Controller Window</h1>
<p>
This document is on the domain: http://codepen.io
</p>
<p>
<button id="send">Send Message</button>
</p>
<iframe id="receiver" src="http://demos.matt-west.com/post-message/receiver.html" width="500" height="200">
<p>Your browser does not support iframes.</p>
</iframe>
回到控制頁面的JS程式碼上來,第一件事情是獲得一個接收視窗的引用receiver,然後取得另外一個按鈕的引用btn。
接著我們需要寫一個方法來處理髮送訊息的過程,當點選“Send Message”按鈕時將呼叫這個方法。在這個方法中我們呼叫receiver變數的postMessage() 方法,並將'Hello Treehouse!'作為我們傳遞的資訊。接收頁面部署在http://demos.matt-west.com上,所以我們將此URL拿來用作targetOrigin引數。
最後我們在btn上建立一個事件監聽器,當點選這個按鈕時,sendMessage()方法將被呼叫 。
window.onload = function() {
// Get the window displayed in the iframe.
var receiver = document.getElementById('receiver').contentWindow;
// Get a reference to the 'Send Message' button.
var btn = document.getElementById('send');
// A function to handle sending messages.
function sendMessage(e) {
// Prevent any default browser behaviour.
e.preventDefault();
// Send a message with the text 'Hello Treehouse!' to the receiver window.
receiver.postMessage('Hello Treehouse!', 'http://demos.matt-west.com');
}
// Add an event listener that will execute the sendMessage() function
// when the send button is clicked.
btn.addEventListener('click', sendMessage);
}
以上是控制頁面需要做的所有事,下面讓我來分析下接收頁面部分的程式碼。
接收視窗
接收視窗的html程式碼非常基礎。唯一一個重要的元素是id號是message的<div>,用來顯示傳遞到視窗的資訊。<h1>Receiver Window</h1>
<p>
This document is on the domain: http://demos.matt-west.com
</p>
<div id="message"></div>
在JS程式碼中我們首先得獲得<div>元素的引用。
接著,我們建立一個方法receiveMessage,當視窗接收到訊息時該方法將被呼叫。在這個方法的內部我們首先檢查訊息確保其來自http://s.codepen.io(控制頁面的域)。任何網站都能夠傳遞訊息到你的頁面所以在執行程式碼前,你得首先檢查資訊的源。通過檢查事件的origin屬性我們能獲得源。然後我們能夠從data屬性中獲取資訊,並通過messageEle來更新內容。
最後,我們設定一個事件監聽器,當message觸發時,我們將來執行receiveMessage()方法。
window.onload = function() {
// Get a reference to the div on the page that will display the
// message text.
var messageEle = document.getElementById('message');
// A function to process messages received by the window.
function receiveMessage(e) {
// Check to make sure that this message came from the correct domain.
if (e.origin !== "http://s.codepen.io")
return;
// Update the div element to display the message.
messageEle.innerHTML = "Message Received: " + e.data;
}
// Setup an event listener that calls receiveMessage() when the window
// receives a new MessageEvent.
window.addEventListener('message', receiveMessage);
}
當你執行這個demo後,你會發現,當你點選“send message”按鈕時Hello Treehouse!將被顯示在iframe內部。
postMessage的瀏覽器支援
瀏覽器支援postMessage有段時間了,IE自IE8後支援postMessage,但是IE8和IE9僅支援使用postMessage在document和iframe間通訊,跨視窗跨tab的支援要到IE10才支援。
IE | FIREFOX | CHROME | SAFARI | OPERA |
---|---|---|---|---|
8+ | 3.0+ | 1.0+ | 4.0+ | 9.5+ |
本文你學習瞭如何使用postMessage實現網頁間的跨域通訊。當使用postMessage時一些安全問題值得留意。首先你得具體化targetOrigin的URL,而不要僅僅使用*,否則你可能不經意傳送資訊到了一些事先不知道的網站。檢查傳送來的資訊的源也是一種保證網頁安全的措施。
當我們使用iframe時,postMessage是唾手可得的工具。
原文連結:http://blog.teamtreehouse.com/cross-domain-messaging-with-postmessage
相關文章
- 使用 postMessage 解決 iframe 跨域通訊問題跨域
- .NET與JSP頁面之間訊息通訊(跨域,使用html5的postMessage實現)JS跨域HTML
- postMessage實現頁面通訊介紹
- bbossmvc結合jsonp實現跨站跨域應用間通訊功能介紹SSMMVCJSON跨域
- 實現兩個視窗通訊方法之postMessage
- 跨源通訊、跨域訪問跨域
- web多應用下跨域通訊視訊教程Web跨域
- 使用HTML5中postMessage 實現ajax中的POST跨域問題HTML跨域
- 使用HTML5中postMessage實現Ajax中的POST跨域問題HTML跨域
- HTML5 window.postMessage 與跨域HTML跨域
- 微服務 - 概念 · 應用 · 通訊 · 授權 · 跨域 · 限流微服務跨域
- Spring Boot 通過CORS實現跨域Spring BootCORS跨域
- 不同頁面通訊與跨域跨域
- 用VC在區域網實現IP多播通訊
- EventBus,輕鬆實現跨元件跨執行緒通訊元件執行緒
- 詳解 CmProcess 跨程式通訊的實現
- php實現SESSION跨域PHPSession跨域
- 父子頁面之間跨域通訊的方法跨域
- [iptables] 基於iptables實現的跨網路通訊
- 封裝一個postMessage庫,進行iframe跨域互動封裝跨域
- 九種方式實現跨域跨域
- Nginx反向代理實現跨域Nginx跨域
- nginx配置CORS實現跨域NginxCORS跨域
- 使用PHP實現跨域COOKIEPHP跨域Cookie
- 【React】元件通訊 - 跨層通訊React元件
- 跨域訪問的解決方案(HTML5的方法:postMessage)跨域HTML
- 跨域方案總結與實現跨域
- 九種跨域方式實現原理跨域
- 多種跨域方式實現原理跨域
- JSONP 跨域原理及實現JSON跨域
- window.name實現跨域功能跨域
- 跨域訪問實現依據跨域
- 最簡單實現跨域的方法:用 Nginx 反向代理跨域Nginx
- 再也不學AJAX了!(三)跨域獲取資源 ③ - WebSocket & postMessage跨域Web
- 使用 `postMessage` 跨域名遷移 `localStorage`跨域
- QT:用QWebSocket實現webchannel,實現C++與HTML通訊QTWebC++HTML
- 瀏覽器跨 Tab 視窗通訊原理及應用實踐瀏覽器
- WPF使用事件聚合器,實現任意頁面跨頁通訊事件