概述
JavaScript出於安全方面的考慮,不允許跨域調用其他頁面的對象。但在安全限制的同時也給注入iframe或是ajax應用上帶來了不少麻煩。這里把涉及到跨域的一些問題簡單地整理一下:
首先什么是跨域,簡單地理解就是因為JavaScript同源策略的限制,a.com 域名下的js無法操作b.com或是c.a.com域名下的對象。更詳細的說明可以看下表:
對於主域相同子域不同的通信方法這里不一一列舉了,這里主要講解一下跨主域的通信問題。
postMessage方法
window.postMessage 是一個用於安全的使用跨源通信的方法。通常,不同頁面上的腳本只在這種情況下被允許互相訪問,當且僅當執行它們的頁面所處的位置使用相同的協議(通常都是 http)、相同的端口(http默認使用80端口)和相同的主機(兩個頁面的 document.domain 的值相同)。 在正確使用的情況下,window.postMessage 提供了一個受控的機制來安全地繞過這一限制。
兼容性
http://caniuse.com/#search=postMessage
具體用法
- 發送消息:destination.postMessage(message, targetOrigin);
- destination: 目標窗口
- message:發送的消息
- targetOrigin: 定義發送消息的范圍
- 監聽接受消息:window.addEventListener(‘message’,callback,false);
已知問題
- 部分版本IE8/9瀏覽器只支持iframe通信,不支持tabs之間通信。
- IE8/9不能傳輸對象,只能傳輸string。
參考資料
- mozlia官方文檔:https://developer.mozilla.org/zh-CN/docs/Web/API/Window.postMessage
- IE官方文檔:https://status.modern.ie/postmessage
- webplatform文檔:https://docs.webplatform.org/wiki/apis/web-messaging/MessagePort/postMessage
- HTML5官方文檔:https://html.spec.whatwg.org/multipage/comms.html#web-messaging
window.navigator(適用於ie6/7)
ie6/7有個漏洞,父窗口與所有的iframe共享window.navigator對象,可以利用這個漏洞,由於ie6/7不支持postMessage,所以可以利用這個漏洞對ie6/7做兼容跨域通信支持。
具體用法
途中A過程和B過程都是初始化監聽事件,類似於onmessage事件。只不過實現方法不一樣而已。
按執行順序來描述的話,如下:
- B: 父窗口向window.navigator添加一個監聽函數,並打上父窗口的戳。
- A: 子窗口向window.navigator添加一個監聽函數,並打上子窗口的戳。
- C: 父窗口執行post的時候,調用原先子窗口添加在navigator里的監聽函數,並將要傳輸的數據作為函數參數傳入。
- D: 子窗口執行post的時候,調用原先父窗口添加在navigator里的監聽函數,並將要傳輸的數據作為函數參數傳入。