1. 程式人生 > 程式設計 >JS跨域之window.name實現的跨域資料傳輸

JS跨域之window.name實現的跨域資料傳輸

一、 window.name的性質

window.name有一個奇妙的性質,
頁面如果設定了window.name,那麼在不關閉頁面的情況下,
使進行了頁面跳轉location.href=...,這個window.name還是會保留。

我們可以在控制檯做一下實驗:

// 開啟瀏覽器輸入URL:www.jb51.net
//F12開啟控制檯
//在控制檯中依次輸入下面內容

//輸入
window.name;
//返回
''

//輸入
window.name='test';
//返回
'test'

//輸入
location.href='http://www.baidu.com';
//返回
http://www.baidu.com

//輸入
window.name;
//返回
'test'

利用這一點,我們就可以拿到其他域中的資料了。

二、 跨域請求

我們知道,使用iframesrc屬性,可以載入不同域中的,
我們也可以使用$('iframe').contentWindow來拿到iframe中頁面的window物件,
只是這個window物件中可以訪問的屬性是很少的。

//控制檯輸入
Object.keys($('iframe').contentWindow);

//返回
["postMessage","blur","focus","close","parent","opener","top","length","frames","closed","location","self","window"]

訪問其他屬性,會報錯:

UncaxaehQught DOMException: Blocked a frame with origin "..." from accessing a cross-origin frame.

而如果使用iframe載入同域的頁面,訪問$('iframe').contentWindow的屬性是不會報錯的,它就是iframe內頁面的完整的window物件。

三、整合

利用window.name的性質,我們可以在iframe中載入一個跨域頁面。

這個頁面載入之後,讓它設定自己的window.name
然後再讓它進行當前頁面的跳轉,跳轉到與iframe外的頁面同域的頁面


此時window.name是不會改變的。

這樣,iframe內外就屬於同一個域了,且window.name還是跨域的頁面所設定的值。

假設有三個頁面:

a.com/app.html:應用頁面。

a.com/proxy.html:代理檔案,一般是一個沒有任何內容的html檔案,需要和應用頁面在同一域下。

b.com/data.html:應用頁面需要獲取資料的頁面,可稱為資料頁面。

實現起來基本步驟如下:

在應用頁面(a.com/app.html)中建立一個iframe,把其src指向資料頁面(b.com/data.html)。
資料頁面會把資料附加到這個iframe的window.name上,data.html程式碼如下:

<script type="text/">
    window.name = 'I was there!';    // 這裡是要傳輸的資料,大小一般為2M,IE和firefox下可以大至32M左右
                                     // 資料格式可以自定義,如on、字串
</script>

在應用頁面(a.com/app.html)中監聽iframe的onload事件,在此事件中設定這個iframe的src指向本地域的代理檔案(代理檔案和應用頁面在同一域下,所以可以相互通訊)。app.html部分程式碼如下:

<script type="text/script">
    var state = 0,iframe = document.createElement('iframe'),loadfn = function() {
        if (state === 1) {
            var data = iframe.contentWindow.name;    // 讀取資料
            alert(data);    //彈出'I was there!'
        } else if (state === 0) {http://www.cppcns.com
            state = 1;
            iframe.contentWindow.location = "http://a.com/proxy.html";    // 設定的代理檔案
        }  
    };
    iframe.src = 'http://b.com/data.html';
    if (iframe.attachEvent) {
        iframe.attachEvent('onload',loadfn);
    } else {
        iframe.onload  = loadfn;
    }
    document.body.appendChild(iframe);
</script>

獲取資料以後銷燬這個iframe,釋放記憶體;這也保證了安全(不被其他域frame js訪問)。

<script type="text/javascript">
    iframe.contentWindow.document.write('');
    iframe.contentWindow.close();
    document.body.removeChild(iframe);
</script>

總結起來即:

iframe的src屬性由外域轉向本地域,跨域資料即由iframe的window.name從外域傳遞到本地域。這個就巧妙地繞過了瀏覽器的跨域訪問限制,但同時它又是安全操作。

參考文章:window.name Transport、Session variables withhttp://www.cppcns.comout cookies

另一篇JS跨域(Access-Control-Allow-Origin)前後端解決方案詳解有更詳細的關於瀏覽器跨域問題介紹