同源定義
若是兩個頁面擁有相同的協議(protocol),端口(若是指定),和主機,那麼這兩個頁面就屬於同一個源(origin)。javascript
如下是同源檢測的示例php
URL | 結果 | 緣由 |
---|---|---|
http://store.company.com/dir2/other.html | Success | |
http://store.company.com/dir/inner/another.html | Success | |
https://store.company.com/secure.html | Failure | 協議不一樣 |
http://store.company.com:81/dir/etc.html | Failure | 端口不一樣 |
http://news.company.com/dir/other.html | Failure | 主機不一樣 |
script標籤是不受同源策略影響的,它能夠引入來自任何地方的js文件。
而jsonp的原理就是,在客戶端和服務端定義一個函數,當客戶端發起一個請求時,服務端返回一段javascript代碼,其中調用了在客戶端定義的函數,並將相應的數據做爲參數傳入該函數。html
function jsonp_cb(data) {
java
console.log(data);
ajax
}
chrome
function ajax(){
json
var url = "http://xx.com/test.php?jsonp_callback=jsonp_cb";
跨域
var script = document.createElement('script');
瀏覽器
// 發送請求
服務器
script.src = url;
document.head.appendChild(script);
}
ajax()
服務端獲取到jsonp_callback傳遞的函數名jsonp_cb,返回一段對該函數調用的js代碼
jsonp_cb({
"name": "story"
});
img標籤也是沒有跨域限制的,但它只能用來發送GET請求,且沒法獲取服務端的響應文本,能夠利用它實現一些簡單的、單向的跨域通訊,例如跟蹤用戶的點擊
var img = new Image();
img.onload = function(){
console.log('done')
img.onload = null;
img = null;
}
img.src = "http://xx/xx.gif"
window對象擁有name屬性,它有一個特色:相同協議下,在一個頁面中,不隨URL的改變而改變
示例代碼
window.name = 'string' // 字符串,通常容許的最大值爲2M
console.log(window.name)
location = 'http://funteas.com/'
此時,在控制檯輸入window.name,結果依然是」string」
window.name // "string"
window.name的值只能是字符串,任何其餘類型的值都會「轉化」爲字符串
例如
window.name = function(){}
console.log(window.name)
// "function(){}"
經過window.name實現跨域也很簡單,iframe擁有contentWindow屬性,其指向該iframe的window對象的引用,若是在iframe的src指向的頁面中設置window.name值,那麼就能夠經過iframe.contentWindow.name就能夠拿到這個值了
var url = "http://funteas.com/lab/windowName";
var iframe = document.createElement('iframe')
iframe.onload = function(){
var data = iframe.contentWindow.name
console.log(data)
}
iframe.src = url
document.body.appendChild(iframe)
然而,chrome會提示你跨域了!
而咱們已經知道window.name不隨URL的改變而改版,也就是說,onload時,已經獲取到了name,只不過由於不一樣源,當前頁面的腳本沒法拿到iframe.contentWindow.name,此時只須要把iframe.src改成同源便可
var url = "http://funteas.com/lab/windowName";
var iframe = document.createElement('iframe')
iframe.onload = function(){
iframe.src = 'favicon.ico';
var data = iframe.contentWindow.name
console.log(data)
}
iframe.src = url
document.body.appendChild(iframe)
刷新頁面,你會發現iframe不斷刷新,這是由於每次onload,iframe的src被修改,而後再次觸發onload,從而致使iframe循環刷新,修改下便可
var url = "http://funteas.com/lab/windowName";
var iframe = document.createElement('iframe')
var state = true;
iframe.onload = function(){
if(state === true){
iframe.src = 'favicon.ico';
state = false;
}else if(state === false){
state = null
var data = iframe.contentWindow.name
console.log(data)
}
}
iframe.src = url
document.body.appendChild(iframe)
上面請求的是一個靜態頁面,而服務端一般須要的是動態數據
echo '<script> window.name = "{\"name\":\"story\"}"</script>';
postMessage容許不一樣源之間的腳本進行通訊,用法
otherWindow.postMessage(message, targetOrigin);
otherWindow 引用窗口 iframe.contentwindow 或 window.open返回的對象
message 爲要傳遞的數據
targetOrigin 爲目標源
// http://127.0.0.1:80
var iframe = document.createElement('iframe')
iframe.onload = function(){
var popup = iframe.contentWindow
popup.postMessage("hello", "http://127.0.0.1:5000");
}
iframe.src = 'http://127.0.0.1:5000/lab/postMessage'
document.body.appendChild(iframe)
// 監聽返回的postMessage
window.addEventListener("message", function(event){
if (event.origin !== "http://127.0.0.1:5000") return;
console.log(event.data)
}, false)
// http://127.0.0.1:5000/lab/postMessage
window.addEventListener("message", function(event){
// 驗證消息來源
if (event.origin !== "http://127.0.0.1") return;
console.log(event.source); // 消息源 popup
console.log(event.origin); // 消息源URI https://secure.example.net
console.log(event.data); // 來自消息源的數據 hello
// 返回數據
var message = 'world';
event.source.postMessage(message, event.origin);
}, false);
CORS(跨域資源共享)是一種跨域訪問的機制,可讓AJAX實現跨域訪問。它容許一個域上的腳本向另外一個域提交跨域 AJAX 請求。實現此功能很是簡單,只需由服務器發送一個響應標頭便可。
Access-Control-Allow-Origin: * // 容許來自任何域的請求
Access-Control-Allow-Origin: http://funteas.com/ // 僅容許來自http://funteas.com/的請求
當客戶端的ajax請求的url爲其餘域時,對於支持CORS的瀏覽器,請求頭會自動添加Origin,值爲當前host
var xhr = new XMLHttpRequest();
var url = 'http://bar.other/resources/public-data/';
xhr.open('GET', url, true);
xhr.send();
CORS默認不發送cookie,若是要發送cookie,須要設置withCredentials
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
同時,服務端也要設置
Access-Control-Allow-Credentials: true
查看MDN關於CORS的介紹【https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS】
以上是我使用過的跨域方式,其餘方式諸如document.domain、flash等,由於沒有用過,就再也不多做介紹,有興趣的同窗能夠本身瞭解下。