同源策略
限制從一個源加載的文檔或者腳本與來自另一個源的資源進行交互。同源策略是一種用於隔離惡意文件的安全機制。
所謂的同源,指的是協議,域名,端口相同。
跨域通信的幾種方式:
- JSONP
- WebSocket
- CORS
- Hash
- PostMessage
JSONP
原理
通過script
標籤異步加載實現。如使用script標籤引入外部文件。
JSONP只支持GET請求。
實現
例一
<script src="http://www.test.com/?data=data&callback=myCallback"/>
例二
<script>
var util = {}
// 定義方法,動態創建script標籤
util.createScript = function(url,charset) {
var script = document.createElement('script');
script.setAttribute('type','text/javaScript');
//定義外部腳本文件中所使用的字符編碼:
charset && script.setAttribute('charset ', charset);
script.setAttribute('src', url);
script.async = true;
return script;
}
util.jsonp = function(url, onsuccess, onerror, charset) {
}
</script>
WebSocket
// 新建 WebSocket 實例。
var ws = new WebSocket("wss://echo.websocket.org");
// webSocket.readyState返回實例對象的當前狀態,共有四種。
// CONNECTING:值爲0,表示正在連接。
// OPEN:值爲1,表示連接成功,可以通信了。
// CLOSING:值爲2,表示連接正在關閉。
// CLOSED:值爲3,表示連接已經關閉,或者打開連接失敗。
switch (ws.readyState) {
case WebSocket.CONNECTING:
// do something
break;
case WebSocket.OPEN:
// do something
break;
case WebSocket.CLOSING:
// do something
break;
case WebSocket.CLOSED:
// do something
break;
default:
// this never happens
break;
}
// 把請求發出去
ws.onopen = function(evt) {
console.log("Connection open ...");
ws.send("Hello WebSockets!");
};
// 接收對方過來的消息
ws.onmessage = function(evt) {
console.log( "Received Message: " + evt.data);
ws.close();
};
// 關閉連接
ws.onclose = function(evt) {
console.log("Connection closed.");
};
http://www.ruanyifeng.com/blog/2017/05/websocket.html
CORS
跨域資源共享(CORS) 是一種機制,它使用額外的 HTTP 頭來告訴瀏覽器 讓運行在一個 origin (domain) 上的Web應用被准許訪問來自不同源服務器上的指定的資源。
fetch是一個新的API,用來實現CORS通信。
fetch('/some/url',{
method: 'get',
}).then(function(res){
// code
}).catch(function(err){
// code
})
http://www.ruanyifeng.com/blog/2016/04/cors.html
Hash
url # 後面的內容就叫hash。Hash的改變頁面不會刷新,這就是Hash做跨域的基本原理。
url ? 後面的內容叫Search,Search的改變會導致頁面刷新。
// 例: 頁面A通過iframe或frame嵌入了跨域頁面B,A給B發消息。
// A頁面
var B = document.getElementByTagName('iframe');
B.src = B.src + '#' + 'jsonString';
// B頁面
// 通過onhashchange方法監聽,url中hash是否發生變化。
window.onhashchange = function(){
var data = window.location.hash;
}
PostMessage
H5 新增postMessage方法可以用作跨域通信。
// 窗口A(http:A.com)向跨域窗口B(http:B.com)發送信息
// A窗口
// A 向B發信息,強調的是B窗口裏的window對象。
window.postMessage('data','http:B.com')
// B 窗口
window.addEventListener("message", function(event){
// 獲取url
console.log(event.origin)
// 獲取A window對象
console.log(event.source)
// 獲取傳過來的數據
console.log(event.data)
});
備註:
舊版本XMLHttpRequest不支持跨域,也就是傳統AJAX不支持跨域;新版本的XMLHttpRequest對象,可以向不同域名的服務器發出HTTP請求。這叫做"跨域資源共享"(Cross-origin resource sharing,簡稱CORS)。
http://www.ruanyifeng.com/blog/2012/09/xmlhttprequest_level_2.html