CORS
CORS是一個(gè)W3C標(biāo)準(zhǔn),全稱(chēng)是"跨域資源共享"(Cross-origin resource sharing)。
什么是跨域
跨域指的是 通過(guò)js在不同的域進(jìn)行通信或傳輸數(shù)據(jù)。比如通過(guò)
<img>標(biāo)簽加載其他域的資源圖片,<script>標(biāo)簽加載其他域的js文件,或者通過(guò)js獲取頁(yè)面中不同域的框架中(iframe)的數(shù)據(jù)。只要域名、協(xié)議、端口號(hào)有任何一個(gè)不同,就屬于不同的域。
跨域方法
XMLHttpRequest對(duì)象
通過(guò)XHR實(shí)現(xiàn)Ajax通信的一個(gè)主要限制,來(lái)源于跨域安全策略。默認(rèn)情況下,XHR 對(duì)象只能訪問(wèn)與包含它的頁(yè)面位于同一個(gè)域中的資源。但是,瀏覽器(IE除外)都通過(guò) XMLHttpRequest對(duì)象實(shí)現(xiàn)了對(duì) CORS 的原生支持。在嘗試打開(kāi)不同來(lái)源的資源時(shí),無(wú)需額外編寫(xiě)代碼就可以觸發(fā)這個(gè)行為。要請(qǐng)求位于另一個(gè)域中的資源,使用標(biāo)準(zhǔn)的 XHR對(duì)象并在 open() 方法中傳入絕對(duì) URL即可。比如:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if (xhr.readyState == 4){
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status== 304){
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
}
};
xhr.open("get", "https://jsonplaceholder.typicode.com/users", true);
xhr.send(null);
Jsonp跨域
通過(guò)
<script>標(biāo)簽加載其他域的資源,服務(wù)器端設(shè)置一個(gè)輔助函數(shù)配合前端回調(diào)函數(shù),返回的是可執(zhí)行的js把它作為回調(diào)函數(shù)的參數(shù)即可得到我們獲取的數(shù)據(jù)。但缺點(diǎn)是只能進(jìn)行g(shù)et方法請(qǐng)求。
頁(yè)面代碼如下:
<!DOCTYPE html>
<html>
<head>
<title>Jsonp</title>
<meta charset="utf-8">
</head>
<body>
<div id="show"></div>
<script type="text/javascript">
function showData(data) {
console.table(data);
}
showData();
</script>
<script type="text/javascript">
window.onload = function(){
let script = document.createElement('script');
script.src = 'https://jsonplaceholder.typicode.com/users'+'?callback=showData';
document.body.appendChild(script);
}
</script>
</body>
</html>
Google控制臺(tái)輸出結(jié)果
result.png
跨文檔消息傳遞
跨文檔消息傳送(cross-document messaging),有時(shí)候簡(jiǎn)稱(chēng)為 XDM,指的是在來(lái)自不同域的頁(yè)面間傳遞消息。例如,www.aa.com域中的頁(yè)面與位于一個(gè)內(nèi)嵌框架p2p.aa.com域中的頁(yè)面通信。
XDM 的核心方法是PostMessage。在 HTML5 規(guī)范中,除了 XDM部分之外的其他部分也會(huì)提到這個(gè)方法名,但都是為了同一個(gè)目的:向另一個(gè)地方傳遞數(shù)據(jù)。對(duì)于 XDM 而言,“另一個(gè)地方”指的是包含在當(dāng)前頁(yè)面中的 <iframe> 元素,或者由當(dāng)前頁(yè)面彈出的窗口。
postMessage() 方法接收兩個(gè)參數(shù):一條消息和一個(gè)表示消息接收方來(lái)自哪個(gè)域的字符串。第二個(gè)參數(shù)對(duì)保障安全通信非常重要,可以防止瀏覽器把消息發(fā)送到不安全的地方。
接收到 XDM 消息時(shí),會(huì)觸發(fā) window 對(duì)象的 message 事件傳遞給 onmessage 處理程序的事件對(duì)象包含以下三方面的重要信息
data :作為 postMessage() 第一個(gè)參數(shù)傳入的字符串?dāng)?shù)據(jù)。origin :發(fā)送消息的文檔所在的域,例如 "http://www.wrox.com"
source :發(fā)送消息的文檔的 window 對(duì)象的代理。這個(gè)代理對(duì)象主要用于在發(fā)送上一條消息的窗口中調(diào)用 postMessage() 方法。如果發(fā)送消息的窗口來(lái)自同一個(gè)域,那這個(gè)對(duì)象就是window
在 onmessage 處理程序中檢測(cè)消息來(lái)源可以確保傳入的消息來(lái)自已知的頁(yè)面
檢測(cè)方法如下
EventUtil.addHandler(window, "message",
function(event){
//確保發(fā)送消息的域是已知的域
if (event.origin == "http://www.wrox.com"){
//處理接收到的數(shù)據(jù)
processMessage(event.data);
//可選:向來(lái)源窗口發(fā)送回執(zhí)
event.source.postMessage("Received!", "http://p2p.wrox.com");
}
});
