IE下因設置document.domain而無法和Iframe通信的解決方法(SCRIPT5: 拒絕訪問)[轉]


IE下因設置document.domain而無法和Iframe通信的解決方法(SCRIPT5: 拒絕訪問)[轉]  

 

 
 

最近在開發SDK的過程中發現IE下有個很怪異的問題:在同一域下,因在父頁面上設置了document.domain,而導致無法正常和Iframe(也是同域下)進行通信,IE下拋出的錯誤是:SCRIPT5: 拒絕訪問,導致無法操作iframe中的內容。

經過查閱了很多資料后發現IE下,在父頁面或在iframe頁面中,只要設置了document.domain,無論是和當前域名相同還是根域名,均視為跨域,所以才會出現拒絕訪問的錯誤,即使你這樣寫document.domain=document.domain;雖然好像沒人這么干。

那么如何才能解決這個問題,讓父頁面和iframe頁面正常通信呢,根據同源策略,讓雙方均設置同樣的domain就可以達到目的。

比如頁面A是http://www.a.com/a.html ,頁面B是http://www.a.com/b.html, 這時候兩個頁面中都寫上document.domain=”aaa.com”,這樣兩個頁面就可以交互了。

但是,上面的情況只適用於嵌入的頁面是事先已經已<iframe src=”http://www.a.com/b.html”></iframe>的形式在頁面中寫好了,而如果是在頁面中動態創建的iframe標簽再指定其src為http://www.a.com/b.html,上面的方法就不適用 了。

此種情況及解決方法請直接參考原著:IE下Iframe的 document.domain的怪異問題

上面的這種情況是當Iframe的src不為空,即存在實際的引用頁面的解決方法。但如果需要創建一個空白的iframe(即src不指定),還要想拿到iframe里的document對象呢?看個例子:

 

//訪問地址:http://www.a.com/a.html

<html>

<head>

<title>Iframe</title>

</head>

<body>

<script type="text/javascript">

document.domain = 'a.com';

var iframe = document.createElement("iframe");

document.body.appendChild(iframe);

iframe.onload = function() {

console.log(iframe.contentWindow.document.location)

}

</script>

</body>

</html>

有人想到設置iframe里面的domain,思路正確,但由於父頁面已經設置了domain,在父頁面中根本無法獲取到空白iframe的document對象,也就無法設置iframe的domain。

 

后來經過了很多嘗試,也研究了twitter的SDK的代碼,找到了解決方案:

通過設置iframe的src來執行一段JS代碼,如下,

1

iframe.src = "javascript:void((function(){document.open();document.domain='"+ document.domain + "';document.close()})())";

通過這種方式就可以改寫iframe里面的domain了,這和在瀏覽器地址欄里輸入這段代碼的功效一樣,這種方式像是旁門左道,但是這確實奏效了。

於是上面的代碼更改為:

 

//訪問地址:http://www.a.com/a.html

<html>

<head>

<title>Iframe</title>

</head>

<body>

<script type="text/javascript">

document.domain = 'a.com';

var iframe = document.createElement("iframe");

document.body.appendChild(iframe);

try{

iframe.contentWindow.document;

catch (e) {

iframe.src = "javascript:void((function(){document.open();document.domain='"+ document.domain + "';document.close()})())";

console.log(iframe.contentWindow.document.location)

}

</script>

</body>

</html>

在IE9下測試順利通過,運行結果:http://www.a.com/a.html,至此,問題看似已經解決。  於是在其他版本的IE瀏覽器下做測試,結果出人意料,IE6-IE8均仍報錯“拒絕訪問”,頭疼,經過反復嘗試,后來無意間在設置iframe.src后,使用了setTimeout來獲取iframe里的內容,靠,居然不報錯了。看來是設置iframe的domain和獲取iframe里面的內容這兩個操作存在異步問題。

然后將上面方法改進:

 

//訪問地址:http://www.a.com/a.html

<html>

<head>

<title>Iframe</title>

</head>

<body>

<script type="text/javascript">

document.domain = 'a.com';

var iframe = document.createElement("iframe");

document.body.appendChild(iframe);

if(/msie/i.test(navigator.userAgent)){

try{

iframe.contentWindow.document;

catch (e) {

iframe.onload = function() {

console.log(iframe.contentWindow.document.location);

iframe.onload = null;

}

iframe.src = "javascript:void((function(){document.open();document.domain='"+ document.domain + "';document.close()})())";

}

}

</script>

</body>

</html>

再次在各IE下做測試,順利通過!至此父頁面因設置了document.domain而導致無法正常和同域下用js動態創建的iframe正常通信的問題徹底得到解決!如果你在開發過程中遇到類似問題,不妨嘗試下這種方法,如果你有更好的解決方案,希望能公開出來供大家一起學習,討論。Demo地址


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM