1、什麼是跨域?
通常來講,向一個非同源網站發送請求獲取數據,就是跨域請求。
同源策略——跨域問題產生緣由
瀏覽器爲了網絡信息安全所採起的的措施,限制資源訪問權限。
來源相同是指:協議、主機(域名),端口號,所有相同。
http://www.example.com/dir/page.html
協議:http
域名:www.example.com
端口:80(默認端口,能夠省略)
- http://www.example.com/dir2/other.html:同源
- http://example.com/dir/other.html:不一樣源(域名不一樣)(域名必須徹底相同)
- http://www.example.com:81/dir/other.html:不一樣源(端口不一樣)
域名級別
一級域名(頂級域名):baidu.com
二級域名:www.baidu.com
三級域名:wangshangyingxiao.club.1688.com
同源策略限制範圍
//若是非同源,共有三種行爲受到限制
(1)cookie、localstorage、IndexDB 沒法讀取
(2)DOM結構沒法得到
(3)AJAX請求不能發送
2、跨域通訊方法
一、設置document.domain
此方法只適用於:兩個網頁一級域名相同,二級域名不一樣(或者三級域名不一樣)
(1)共享
cookie;(2)iframe窗口,獲取dom結構。
實現方法:
兩個網頁設置相同的document.domain,設置爲一級域名,便可共享cookie
情景1:
實現cookie共享,兩個網頁一級域名相同,二級域名不一樣。
cookie是服務器寫入瀏覽器的信息,只有同源的網頁才能夠共享。
//舉例說明:
//設置相同的domain
document.domain = 'example.com'
;
//設置後
//A頁面,設置cookie
document.cookie = 'test=hello';
//B頁面,獲取cookie
document.cookie //cookie的值中包含設置的test=hell
服務器也能夠在設置cookie時,指定cookie的所屬域名爲一級域名, 這樣的話,二級域名和三級域名不用作任何設置,均可以讀取到這個cookie。
情景2:獲取iframe的Dom結構,兩個網頁一級域名相同,二級域名不一樣。
iframe Dom結構:只有同源的頁面才能夠相互通訊,獲取DOM結構。
//舉例說明:
//設置前,非同源頁面,父窗口獲取子窗口dom,報錯
document.getElementById('#myIframe').contentWindow.document
//Uncaught DOMException: Blocked a frame
from accessing a cross-origin frame.
//
設置前,
非同源頁面,
子
窗口獲取父窗口dom,報錯
window.parent.document.body
//Uncaught DOMException: Blocked a frame
from accessing a cross-origin frame.
//設置相同的domain
//設置後,便可獲取Dom
二、片斷識別符 (fragment identifier)
針對徹底不一樣源的主頁面與iframe頁面,解決跨域通訊的問題。將通訊內容寫入片斷標識符中。
片斷識別符是指URL中#號後面的部分,例如:http://example.com/x.html#fragment的#fragment。
只更改片斷標識符,頁面不會從新刷新。
缺點:片斷標識符中數據長度受限
//父窗口將信息,寫入子窗口的片斷標識符
var
iframeEle = document.
getElementById
(
'iframe'
)
;
console.
log
(
"父頁面:"
+ location.href)
;
// console.log("父頁面獲取子頁面url:" + iframeEle.contentWindow.location.href);//報錯,跨域
/*片斷標識符跨域*/
iframeEle.src = iframeEle.src +
'#faterData'
;
window.
onhashchange
=
function
(){
console.
log
(
'父窗口hash變化:'
+ window.location.hash)
;
}
//子窗口監聽hashchange事件獲得通知
console.
log
(
"子頁面:"
+ location.href)
;
// console.log("子頁面獲取父頁面url:" + top.location.href);//報錯,跨域
/*片斷標識符跨域*/
window.
onhashchange
=
function
(){
console.
log
(
'子窗口hash變化:'
+ window.location.hash)
;
}
;
top.location.href =
"http://localhost:63342/luna_gather/src/index_test.html#childData3";
;
// top.location.href = top.location.href + "#childData2"; ////報錯,跨域
3.window.name
瀏覽器窗口有window.name屬性,這個屬性的特色是:只要在同一窗口中,不管是否同源,不一樣網頁的window.name屬性都是共享的。
優勢:window.name數據容量大(相比片斷識別符)
缺點:(1)必須同一窗口;(2)必須監聽窗口window.name屬性的變化,影響網頁性能;
4.postMessage
能夠實現徹底不一樣源的窗口進行有限的通訊。
語法:
(1)發送方發送消息
otherWindow.postMessage(message,targetOrigin,[transfer]);
①otherWindow:其餘窗口的引用,如(1)iframeEle.contentWindow;(2)window.open返回的窗口對象;(3)命名過或數值索引的window.frames,如window.frames[0]
②message:傳送數據
③targetOrigin:指定接受數據的窗口的源,能夠爲特定url,或者「*」,表示所有窗口
④transfer:
是一串和message同時傳遞的Transferable對象,這些對象的全部權將被轉移給消息的接收方,而發送方將再也不保留全部權。
(2)接收方,監聽message事件,接收消息
window.addEventListener('message',function(event){});
messageEvent涉及到如下四個屬性:
①type:message的類型
②data:postMessage發送過來的數據
③origin:調用postMessage方法的窗口的源,即發送消息的窗口的源
④source:調用postMessage方法的窗口對象
(3)案例演示
父頁面:http://a.com/main.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<iframe id="iframe" src="http://b.com/iframe.html" frameborder="0"></iframe>
</body>
<script type="text/javascript">
window.onload = function(){
var iframeEle = document.getElementById('iframe');
console.log("父頁面:" + location.href);
// console.log("父頁面獲取子頁面url:" + iframeEle.contentWindow.location.href);//報錯,跨域
/*postMessage跨域*/
window.frames[0].postMessage("我是父頁面", '*');//第一種方式
iframeEle.contentWindow.postMessage("我是父頁面2", 'http://b.com/';);//第二種方式
window.addEventListener('message',function(e){
console.log("父窗口接受數據:" + e.data);
});
}
</script>
</html>
子頁面:http://b.com/iframe.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<iframe id="iframe" src="http://b.com/iframe.html"; frameborder="0">
</iframe>
</body>
<script type="text/javascript">
window.onload = function(){
console.log("子頁面:" + location.href);
// console.log("子頁面獲取父頁面url:" + top.location.href);//報錯,跨域
/*postMessage跨域*/
top.postMessage('我是子頁面','http://a.com/main.html');
window.addEventListener('message',
function(e){
console.log('子窗口接受數據:' + e.data);
e.source.postMessage('我接受到數據了','*');
},
false);
}
</script>
</html>
注意:postMessage必定要在頁面完成加載以後執行(即onload以後),不然會報錯:
Failed to execute ‘postMessage’ on ‘DOMWindow’
能夠利用postMessage,實現跨域窗口的localstorage操做。
五、AJAX
同源政策限制,AJAX請求只能發給同源網址,不然跨域報錯。
除了架設服務器代理外,(即瀏覽器請求同源服務器,再由後者請求外部服務器),有三種方法規避同源限制
一、JSONP
二、WebSocket
三、CORS
具體內容,以後單獨列出。