什麼是跨域?跨域解決方法
一、為什麼會出現跨域問題
出於瀏覽器的同源策略限制。同源策略(Sameoriginpolicy)是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能都會受到影響。可以說Web是構建在同源策略基礎之上的,瀏覽器只是針對同源策略的一種實現。同源策略會阻止一個域的javascript指令碼和另外一個域的內容進行互動。所謂同源(即指在同一個域)就是兩個頁面具有相同的協議(protocol),主機(host)和埠號(port)
二、什麼是跨域
當一個請求url的協議、域名、埠三者之間任意一個與當前頁面url不同即為跨域
當前頁面url |
被請求頁面url | 是否跨域 | 原因 |
http://www.test.com/ | http://www.test.com/index.html | 否 | 同源(協議、域名、埠號相同) |
http://www.test.com/ | https://www.test.com/index.html | 跨域 | 協議不同(http/https) |
http://www.test.com/ | http://www.baidu.com/ | 跨域 | 主域名不同(test/baidu) |
http://www.test.com/ | http://blog.test.com/ | 跨域 | 子域名不同(www/blog) |
http://www.test.com:8080/ | http://www.test.com:7001/ | 跨域 | 埠號不同(8080/7001) |
三、非同源限制
【1】無法讀取非同源網頁的 Cookie、LocalStorage 和 IndexedDB
【2】無法接觸非同源網頁的 DOM
【3】無法向非同源地址傳送 AJAX 請求
四、跨域解決方法
【1】設定document.domain解決無法讀取非同源網頁的 Cookie問題
因為瀏覽器是通過document.domain屬性來檢查兩個頁面是否同源,因此只要通過設定相同的document.domain,兩個頁面就可以共享Cookie
// 兩個頁面都設定
document.domain = 'test.com';
【2】跨文件通訊 API:window.postMessage()
呼叫postMessage方法實現父視窗http://test1.com向子視窗http://test2.com發訊息(子視窗同樣可以通過該方法傳送訊息給父視窗)
// 父視窗開啟一個子視窗
var openWindow = window.open('http://test2.com', 'title');
// 父視窗向子視窗發訊息(第一個引數代表傳送的內容,第二個引數代表接收訊息視窗的url)
openWindow.postMessage('Nice to meet you!', 'http://test2.com');
呼叫message事件,監聽對方傳送的訊息
// 監聽 message 訊息
window.addEventListener('message', function (e) {
console.log(e.source); // e.source 傳送訊息的視窗
console.log(e.origin); // e.origin 訊息發向的網址
console.log(e.data); // e.data 傳送的訊息
},false);
【3】JSONP
JSONP 是伺服器與客戶端跨源通訊的常用方法。最大特點就是簡單適用,相容性好(相容低版本IE),缺點是隻支援get請求,不支援post請求。
核心思想:網頁通過新增一個<script>元素
,向伺服器請求 JSON 資料,伺服器收到請求後,將資料放在一個指定名字的回撥函式的引數位置傳回來。
<script src="http://test.com/data.php?callback=dosomething"></script>
// 向伺服器test.com發出請求,該請求的查詢字串有一個callback引數,用來指定回撥函式的名字
// 處理伺服器返回回撥函式的資料
<script type="text/javascript">
function dosomething(data){
//處理獲得的資料
}
</script>
【4】CORS
CORS 是跨域資源分享(Cross-Origin Resource Sharing)的縮寫。它是 W3C 標準,屬於跨源 AJAX 請求的根本解決方法。
1.前端程式碼(需要判斷瀏覽器是否支援情況)
function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// 此時即支援CORS的情況
// 檢查XMLHttpRequest物件是否有“withCredentials”屬性
// “withCredentials”僅存在於XMLHTTPRequest2物件裡
xhr.open(method, url, true);
} else if (typeof!= "undefined") {
// 否則檢查是否支援XDomainRequest,IE8和IE9支援
// XDomainRequest僅存在於IE中,是IE用於支援CORS請求的方式
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// 否則,瀏覽器不支援CORS
xhr = null;
}
return xhr;
}
var xhr = createCORSRequest('GET', url);
if (!xhr) {
throw new Error('CORS not supported');
}
2.伺服器
伺服器端對於CORS的支援,主要是通過設定Access-Control-Allow-Origin來進行的。如果瀏覽器檢測到相應的設定,就可以允許Ajax進行跨域的訪問。我們主要介紹Apache和PHP裡的設定方法
Apache需要使用mod_headers模組來啟用HTTP頭的設定,它預設是啟用的。你只需要在Apache配置檔案的<Directory>, <Location>, <Files>或<VirtualHost>的配置里加入以下內容即可
Header set Access-Control-Allow-Origin *
PHP使用如下程式碼設定即可
<?php
header("Access-Control-Allow-Origin:*");