1. 程式人生 > >什麼是跨域?跨域解決方法

什麼是跨域?跨域解決方法

一、為什麼會出現跨域問題

出於瀏覽器的同源策略限制。同源策略(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:*");