怎樣利用window.name跨域
1. window.name
的性質
window.name
有一個奇妙的性質,
頁面如果設定了window.name
,那麼在不關閉頁面的情況下,
即使進行了頁面跳轉location.href=...
,這個window.name
還是會保留。
我們可以在控制檯做一下實驗:
// 開啟必應 https://www.bing.com/ // 保留控制檯log(勾上Preserve log > window.name "" > window.name='test'; "test" > location.href='http://www.google.com'; "http://www.google.com" Navigated to https://www.google.com/ > window.name "test"
利用這一點,我們就可以拿到其他域中的資料了。
2. 跨域請求
我們知道,使用iframe
的src
屬性,可以載入不同域中的網頁,
我們也可以使用$('iframe').contentWindow
來拿到iframe
中頁面的window
物件,
只是這個window
物件中可以訪問的屬性是很少的。
> Object.keys($('iframe').contentWindow); ["postMessage", "blur", "focus", "close", "parent", "opener", "top", "length", "frames", "closed", "location", "self", "window"]
訪問其他屬性,會報錯:
Uncaught DOMException: Blocked a frame with origin "..." from accessing a cross-origin frame.
而如果使用iframe載入同域的頁面,訪問$('iframe').contentWindow
的屬性是不會報錯的,它就是iframe
內頁面的完整的window
物件。
3. 整合
利用window.name
的性質,我們可以在iframe
中載入一個跨域頁面。
這個頁面載入之後,讓它設定自己的window.name
,
然後再讓它進行當前頁面的跳轉,跳轉到與iframe外的頁面同域的頁面,
此時window.name
這樣,iframe
內外就屬於同一個域了,且window.name
還是跨域的頁面所設定的值。
假設我們有3個頁面,a.com/index.html
a.com/empty.html
b.com/index.html
(1)在a.com/index.html
頁面中嵌入一個iframe
,設定src
為b.com/index.html
(2)b.com/index.html
載入後,設定window.name
,然後再使用location.href='a.com/empty.html'
跳轉到與iframe
外頁面同域的頁面中。
(3)在a.com/index.html
頁面中,就可以通過$('iframe').contentWindow.name
來獲取iframe
內頁面a.com/empty.html
的window.name
值了,而這個值正是b.com/index.html
設定的。
注意:
(1)讓iframe
內的跨域頁面,在設定了window.name
之後,跳轉到與iframe
外頁面同域的頁面,這個過程是必須,否則通過$('iframe').contentWindow.name
訪問會報跨域錯誤。
(2)實際操作中,我們一般使用一個隱藏的iframe
,然後監聽它第二次onload
事件,就知道該iframe
已經跳到同域頁面了,然後使用$('iframe').contentWindow.name
即可。