一、同源策略
同源就是當(dāng)協(xié)議、域名和端口都一致時(shí),才算是同源,有一個(gè)不同都不是同源。
同源策略官方解釋就是,限制從一個(gè)源加載的文檔或腳本如何與來(lái)自另一個(gè)源的資源進(jìn)行交互。這是一個(gè)用戶(hù)隔離潛在惡意文件的關(guān)鍵的安全機(jī)制。
不是同源,主要會(huì)有以下限制:
- cookie、LocalStorage和IndexDB無(wú)法讀取
- DOM無(wú)法獲取
- Ajax請(qǐng)求不能發(fā)送
二、前后端如何通信
- ① Ajax ,受同源策略限制
- ② WebSocket,不受同源策略限制
- ③ CORS,既支持跨域通信,也支持同源通信
三、如何創(chuàng)建Ajax
創(chuàng)建一個(gè)Ajax,主要考慮如下問(wèn)題:
- XMLHttpRequest 對(duì)象的工作流程
- 兼容性的處理
- 事件的觸發(fā)條件
- 事件的觸發(fā)順序
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>
function loadXMLDoc()
{
var xmlhttp;
var txt,x,i;
// 判斷XMLHttpRequest是否存在
if (window.XMLHttpRequest)
{
// IE7+, Firefox, Chrome, Opera, Safari 瀏覽器執(zhí)行代碼
xmlhttp=new XMLHttpRequest();
}
else
{
// IE6, IE5 瀏覽器執(zhí)行代碼
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
xmlDoc=xmlhttp.responseXML;
txt="";
x=xmlDoc.getElementsByTagName("ARTIST");
for (i=0;i<x.length;i++)
{
txt=txt + x[i].childNodes[0].nodeValue + "<br>";
}
document.getElementById("myDiv").innerHTML=txt;
}
}
xmlhttp.open("GET","cd_catalog.xml",true);
xmlhttp.send();
}
</script>
</head>
<body>
<h2>我收藏的 CD :</h2>
<div id="myDiv"></div>
<button type="button" onclick="loadXMLDoc()">獲取我的 CD</button>
</body>
</html>
創(chuàng)建一個(gè)Ajax的基本步驟:
- (1)創(chuàng)建XMLHttpRequest對(duì)象,也就是創(chuàng)建一個(gè)異步調(diào)用對(duì)象。
- (2)創(chuàng)建一個(gè)新的HTTP請(qǐng)求,并指定請(qǐng)求的方法、URL、是否異步處理請(qǐng)求及驗(yàn)證信息。
- (3)為onreadystatechange 事件綁定方法,監(jiān)聽(tīng)狀態(tài)的改變。
- (4)發(fā)送HTTP請(qǐng)求。
四、跨域通信的幾種方式
- JSONP
只支持GET請(qǐng)求
利用script標(biāo)簽支持跨域的屬性,用script標(biāo)簽?zāi)玫桨藬?shù)據(jù)的方法(相當(dāng)于是返回了一段js代碼),在請(qǐng)求中包含callback,服務(wù)端注入?yún)?shù)后返回這個(gè)回調(diào)函數(shù),然后script標(biāo)簽?zāi)玫椒祷氐膉s代碼跨域直接運(yùn)行回調(diào),需要前后端的配合。 - Hash
原理是利用location.hash來(lái)進(jìn)行傳值。在url: http://a.com#helloword中的‘#helloworld’就是location.hash,改變hash并不會(huì)導(dǎo)致頁(yè)面刷新,所以可以利用hash值來(lái)進(jìn)行數(shù)據(jù)傳遞,當(dāng)然傳遞數(shù)據(jù)的大小是有限的。 - postMessage
// 窗口A(yíng)(http://A.com)向跨域窗口B(http://B.com)發(fā)送信息
window.postMessage('data', 'http://B.com');
// 在窗口B中監(jiān)聽(tīng)
window.addEventListener('message', function(event){
console.log(event.origin); // http://A.com
console.log(event.source); // A的window
console.log(event.data); // data
})
- WebSocket
特點(diǎn)包括:
(1)建立在 TCP 協(xié)議之上,服務(wù)器端的實(shí)現(xiàn)比較容易。
(2)與 HTTP 協(xié)議有著良好的兼容性。默認(rèn)端口也是80和443,并且握手階段采用 HTTP 協(xié)議,因此握手時(shí)不容易屏蔽,能通過(guò)各種 HTTP 代理服務(wù)器。
(3)數(shù)據(jù)格式比較輕量,性能開(kāi)銷(xiāo)小,通信高效。
(4)可以發(fā)送文本,也可以發(fā)送二進(jìn)制數(shù)據(jù)。
(5)沒(méi)有同源限制,客戶(hù)端可以與任意服務(wù)器通信。
(6)協(xié)議標(biāo)識(shí)符是ws(如果加密,則為wss),服務(wù)器網(wǎng)址就是 URL。
var ws = new Websocket('wss://echo.websocket.org');
ws.onopen = function(evt) {
console.log('Connection open...');
ws.send('Hello world!');
};
ws.onmessage = function (evt) {
console.log('Received Message' + evt.data);
ws.close();
};
ws.onclose = function (evt) {
console.log('Connection closed');
}
- CORS
為什么CORS能支持跨域通信?
瀏覽器會(huì)攔截Ajax請(qǐng)求,如果瀏覽器發(fā)現(xiàn)這個(gè)Ajax請(qǐng)求時(shí)跨域的,它會(huì)在HTTP請(qǐng)求頭中加一個(gè)origin。