CORS跨域資源共享簡述


什么是CORS?

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

如何使用CORS?

使用CORS需要客戶端和服務端兩者配合。

一、客戶端如何發起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還需要服務端來配合。

二、服務器如何允許客戶的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,它的請求過程如下:

1.XHR對象send發出請求

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

  • 表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.如果服務端判斷上面設置的額外信息可以允許請求,那么就會再請求一次正常的請求了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM