使用 postMessage + iframe 實現跨域通信

一、postMessage

window.postMessage() 方法可以安全地實現跨源通信。通常,對於兩個不同頁面的腳本,只有當執行它們的頁面位於具有相同的協議(通常爲https),端口號(443爲https的默認值),以及主機(兩個頁面的模數 Document.domain設置爲相同的值)時,這兩個腳本才能相互通信。window.postMessage() 方法提供了一種受控機制來規避此限制,只要正確的使用,這種方法就很安全。

調用 postMessage() 方法時,向目標窗口派發一個 Event 消息。 該 Event 消息的 data 屬性爲 postMessage() 的數據;origin 屬性表示調用 postMessage() 方法的頁面的地址。

二、語法

otherWindow.postMessage(message, targetOrigin)

說明

  • otherWindow:其他窗口的一個引用,比如 iframe 的 contentWindow 屬性、執行 window.open 返回的窗口對象、或者是命名過或數值索引的 window.frames。
  • message:將要發送到其他 window 的數據。它將會被結構化克隆算法序列化。這意味着你可以不受什麼限制的將數據對象安全的傳送給目標窗口而無需自己序列化。
  • targetOrigin:通過窗口的 origin 屬性來指定哪些窗口能接收到消息事件,其值可以是字符串 * (表示無限制)或者一個 URI。在發送消息的時候,如果目標窗口的協議、主機地址或端口這三者的任意一項不匹配 targetOrigin 提供的值,那麼消息就不會被髮送;只有三者完全匹配,消息纔會被髮送。

三、示例

我配了兩個域名 example.mazey.cnexample0.mazey.cn,其中 http://example0.mazey.cn/post-message/send.html 會給 http://example.mazey.cn/post-message/receive.html 發送一條消息 Message From Mazey.

send.html

<script>
  window.onload = function () {
    window.parent.postMessage(
      'Message From Mazey.',
      '*'
    )
  }
</script>

receive.html

<script>
  // 監聽
  window.addEventListener(
    'message',
    event => {
      let origin = event.origin || event.originalEvent.origin
      console.log(event, origin, event.data) // MessageEvent{...} "http://example0.mazey.cn" "Message From Mazey."
    }
  )
  // 使用 JS 加載 iframe,保證監聽創建後再加載 iframe。
  let iframeEle = document.createElement('iframe')
  iframeEle.src = 'http://example0.mazey.cn/post-message/send.html'
  iframeEle.style = 'border: none;width: 0;height: 0;'
  document.body.insertBefore(iframeEle, document.body.firstChild)
</script>

注意

如果發送的消息有敏感信息(例如:密碼),始終驗證接受時的 event.origin 和指定發送時的 targetOrigin。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章