CORS跨域資源共享簡述

什麼是CORS?

默認狀況下,爲預防某些而已行爲,瀏覽器的XHR對象只能訪問來源於同一個域中的資源。可是咱們在平常實際開發中,經常會遇到跨域請求的需求,所以就出現了一種跨域請求的方案:CORS(Cross-Origin Resource Sharing)跨域資源共享。
CORS背後的原理是:使用自定的HTTP頭部與服務器進行溝通,從而由服務器決定響應是否成功api

如何使用CORS?

使用CORS須要客戶端和服務端二者配合。跨域

1、客戶端如何發起CORS跨域請求?

目前在大多數瀏覽器下(CORS在各瀏覽器下支持狀況),都原生支持CORS,代碼編寫時和同域的請求差很少,只須要在xhr.open()的時候傳入絕對URL便可。例如:瀏覽器

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
    if(xhr.readyState == 4){
        if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
            console.log(xhr.responseText)
        }else {
            console.log('err' + xhr.status);
        }
    }
};
xhr.open('get','http://www.xxx.com/api/something/',true);
xhr.send(null);

這樣就能夠發送一個跨域請求了,可是若是隻是如上面示例代碼同樣發送的話會報錯,由於服務器並未設置容許咱們這個請求,所以CORS還須要服務端來配合。緩存

2、服務器如何容許客戶的CORS跨域請求?

服務器只須要在響應頭部中設置Access-Control-Allow-Origin便可讓客戶端訪問。安全

假設客戶端的域名是http://www.xxx.com,那麼服務端只要在Access-Control-Allow-Origin的設置中含有http://www.xxx.com,那麼這個CORS請求便可成功。若是Access-Control-Allow-Origin設置爲*,那麼任意域名均可以訪問這個服務端,可是爲了安全起見,通常並不建議這樣作。服務器

如下截圖是一個CORS請求後服務端正常返回的示例:併發

cors2.png

Preflighted Request

CORS還有一種叫作Preflighted Request(預飛請求)的透明服務器驗證機制完成請求過程,若是你在請求的時候使用了表1中的選項來發送請求(使用setRequestheaders設定自定義頭部),那麼就會觸發Preflighted Request,它的請求過程以下:cors

1.XHR對象send發出請求url

2.瀏覽器先向服務端發出一個OPTIONS方法的請求,併發送下列頭部:code

  • 表1
請求頭部信息 含義
Origin 來源域名,與簡單的請求相同。
Access-Control-Request-Method 請求自身使用的方法。
Access-Control-Request-Headers (可選) 自定義的頭部信息,多個頭部以逗號分隔。

OPTIONS請求示例:
客戶端請求的代碼(比上面多加了個header):

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
    if(xhr.readyState == 4){
        if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
            console.log(xhr.responseText)
        }else {
            console.log('err' + xhr.status);
        }
    }
};
xhr.open('get','http://www.xxx.com/api/poisearch/',true);
xhr.setRequestHeader('haha',1);
xhr.send(null);

請求結果(這裏OPTIONS請求觸發了,但沒有找到這個url):
preflight.png

3.服務器接收到這個請求後,根據上面的頭部信息判斷是否予以接收。並在響應中發送以下頭部與瀏覽器進行溝通:

  • 表2
響應頭部信息 含義
Access-Control-Allow-Origin 來源域名,與簡單的請求相同。
Access-Control-Allow-Methods 容許的方法,多個方法以逗號分隔。
Access-Control-Allow-Headers(可選) 容許的頭部,多個頭部以逗號分隔。
Access-Control-Max-Age 應該將這個Preflight請求緩存多長時間(以秒錶示)

4.Preflighted Request結束後,結果將按照指定的時間緩存起來。

5.若是服務端判斷上面設置的額外信息能夠容許請求,那麼就會再請求一次正常的請求了。

相關文章
相關標籤/搜索