Iframe簡單探索以及Iframe跨域處理

探索Iframe

本文目的:html

  • Iframe簡單使用算法

  • Iframe跨域json

  • Iframe常見問題segmentfault


一.Iframe基本Dom以及經常使用屬性和經常使用事件

1.DOM:

<iframe class="iframe" style="height: 100%;width: 100%;border: 0;"  id="Yiframe" name="Yiframe" src='http://localhost:2255/67iframe-2.html' ></iframe>

2.經常使用屬性:

和平時使用的DOM標籤相似,樣式之類的仍是建議用class吧,統一塊兒來方便管理。跨域

更多屬性看:http://www.runoob.com/tags/ta...數組

3.經常使用事件:

<iframe> 標籤支持 HTML 的事件屬性瀏覽器

通常用這個就夠了安全

onload:當文檔加載時運行腳本app

document.querySelector('#Yiframe').onload = function(event){
            console.log('onload',event);
        }

二.JS動態新增並插入Iframe

和平時新增DOM標籤同樣便可。框架

var iframe = document.createElement('iframe');
     iframe.src = url;
     iframe.id = "Yiframe";
     iframe.style="height: 100%;width: 100%;border: 0;";
     $('.content').append(iframe);

三.iframe與父頁面互動

1.注意事項

(1). 必須是在二者同域的狀況下才能進行數據交互。

(2). 中間不管嵌套幾回iframe,只要其中一個iframe與上級或者上上級同域,二者以前就能進行相互調用

2.實現方案(同域)

(1).父頁面獲取子頁面

document.querySelector('#XXXX').contentWindow

window.frames[x]

能夠獲取到iframe內的window對象,包括iframe內自行聲明的全局方法等。

window.frames注意事項:
  • 該屬性返回窗口中全部命名的框架(<iframe>)。

  • 直接打印window.frames不是數組對象。

  • frames.length 來獲取框架的數量。

  • 能夠經過window.frames[數字]直接獲取iframe內的window對象。

(2).子頁面獲取父頁面

window.parent

能夠獲取到父頁面的window對象,包括父頁面內自行聲明的全局方法等。

3.跨域(未跨主域)

(1).嘗試。

打印 document.querySelector('#XXXX').contentWindow 和 window.parent 能夠看到裏面的屬性和方法(第一層/第二層)。

但關鍵數據和方法會被和諧。

image

(2).修改document.domain實現跨域通訊

網上搜到這個方法,但本身嘗試的時候總會報錯:

VM301:1 Uncaught DOMException: Failed to set the 'domain' property on 'Document': 'baidu.com' is not a suffix of 'corp.dinghuo123.com'.
    at <anonymous>:1:17

由於同源安全政策不能直接修改。

首先補充一個知識點,而後再講解怎麼使用。

知識點:

一級域名 有的人叫根域名,如:dinghuo123.com、baidu.com、xx.com.cn、xx.cn.net 等等。

二級域名 是指增長了一級,包括www。如:www.dinghuo123.com、corp.dinghuo123.com、agent.dinghuo123.com 等等。因此有人把www.dinghuo123.com叫一級域名這是錯誤的。

document.domain 能夠修改 corp.dinghuo123.com、agent.dinghuo123.com 爲同一個主域 dinghuo123.com,此時便可經過上面步驟三-2實現父子之間的通訊。

可是跨主域的時候就不能用這個方法了。

4.跨域(跨主域)

(1)方法

發送方:
otherWindow.postMessage(message, targetOrigin, [transfer]);

otherWindow

//其餘窗口的一個引用,
//(1)好比iframe的contentWindow屬性、
//(2)執行window.open返回的窗口對象、
//(3)或者是命名過或數值索引的window.frames。
//(4)父級parent.window對象

message

//將要發送到其餘 window的數據。它將會被結構化克隆算法序列化。這意味着你能夠不受什麼限制的將數據對象安全的傳送給目標窗口而無需本身序列化。
//PS我的以爲如果對象儘可能仍是自行序列化吧避免出現什麼奇怪的問題。

targetOrigin

//經過窗口的origin屬性來指定哪些窗口能接收到消息事件,其值能夠是字符串"*"(表示無限制)或者一個URI。在發送消息的時候,若是目標窗口的協議、主機地址或端口這三者的任意一項不匹配targetOrigin提供的值,那麼消息就不會被髮送;只有三者徹底匹配,消息纔會被髮送。這個機制用來控制消息能夠發送到哪些窗口;例如,當用postMessage傳送密碼時,這個參數就顯得尤其重要,必須保證它的值與這條包含密碼的信息的預期接受者的orign屬性徹底一致,來防止密碼被惡意的第三方截獲。若是你明確的知道消息應該發送到哪一個窗口,那麼請始終提供一個有確切值的targetOrigin,而不是*。不提供確切的目標將致使數據泄露到任何對數據感興趣的惡意站點。
//PS簡單來講就是*的話對方不管是什麼URL都會觸發onmessage回調,若是不是就會報錯(圖片見下方)


transfer //可選

//是一串和message 同時傳遞的 Transferable 對象. 這些對象的全部權將被轉移給消息的接收方,而發送一方將再也不保有全部權。
//PS這個不是很懂,後面有時間研究。

targetOrigin報錯圖
圖片描述

postMessage兼容性
圖片描述

監聽方:
window.onmessage = function(e){ console.log(e)}

e.source //能夠得到父級window對象(必須是同域)
e.origin  //檢查postMessage的發送頁面的源。

(2)實踐

父向子

//父:
document.querySelector('#xx').onclick = function(){
    window.frames[0].postMessage('testPost','*'); 
    //document.querySelector('#Yiframe').contentWindow.postMessage('testPost','*'); 也能夠
}
//子:
window.onmessage =function(e){
    console.log('onmessage2',e,document.domain);
}

子向父

//子:
document.querySelector('#btn5').addEventListener('click',function(){
    parent.window.postMessage('testChildPost','*');
});

//父:
window.onmessage = function(e){ 
    console.log('onmessage父',e) 
}

兩個窗口:

理論上把window對象瀏覽器存儲下再用上面的方式就能實現。何嘗試。

(3)安全問題

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

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

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

四.路由變化以及前進後退。

  1. 控制檯使用window.location.href會致使瀏覽器的url變化。

  2. 用戶點擊後退或者前進的時候,會根據以前的操做,徹底依次復現(變化瀏覽器url和iframe內部頁面路由變化)

  3. window.history.go(xx) 和 window.history.back() ,不管在父頁面仍是在子頁面中,使用的效果和瀏覽器的前進後退是同樣的。

  4. iframe中的頁面使用window.location.href(和a標籤)改變路由的時候不會引起瀏覽器url的變化,但會新增一條歷史記錄

  5. iframe每次重載,都會觸發onload事件。

五.常見問題

  1. iframe內的路由變化,iframe的src值不會變!!!

  2. 要獲取iframe內的當前url,用document.querySelector('#Yiframe').contentWindow.location.href;

  3. parent.window 在沒有父級的時候 parent.window = window;

參考資料

SO JSON在線解析:http://www.sojson.com/blog/17...

瀏覽器同源政策: https://developer.mozilla.org...

postMessage:https://developer.mozilla.org...

相關文章
相關標籤/搜索