CORS(cross-origin-resource-sharing)跨源資源共享


其實就是跨域請求。我們知道XHR只能訪問同一個域中的資源,這是瀏覽器的安全策略所限制,但是開發中合理的跨域請求是必須的。CORS是W3的一個工作草案,基本思想就是:使用自定義的HTTP頭部讓瀏覽器與服務器溝通,決定響應成功或失敗。

CORS需要瀏覽器和服務器同時支持,所有瀏覽器都支持該功能,IE瀏覽器在IE10以上支持。

CORS跟同源AJAX請求差別不大,主要是瀏覽器發現Ajax跨域請求時候,自動添加一些附加的頭部信息,有時多一次附加的OPTIONS預檢查請求,但用戶不會感知。

(閑話:實際項目中經常遇到Access-Control-Allow-Origin報錯,network里面請求數據時候會多請求一次methods為options方法的請求,它返回200后才真正再去請求一次真正的接口請求,這都是請求跨域時候的表現)

Important Part:CORS將請求分成兩大類,simple request(簡單請求)和not-so-simple request(非簡單請求)

簡單請求的請求方法是:HEAD GET POST其中之一

頭部信息不超過下面幾種字段:

Accept

Accept-Language

Content-Language

Last-Event-ID

Content-Type:application/x-www-form-urlencoded,multipart/form-data,text/plain

不是簡單請求的就是復雜請求了。

瀏覽器處理簡單請求步驟:

直接發起CORS請求,在request header里面添加origin字段源Url(協議+域名+端口號),如果不在許可范圍內部,服務器也是返回正常的HTTP response,但是response header里面沒有包含Access-Control-Allow-Origin字段,console控制台報錯,被瀏覽器的XHR對象的onerror回調捕獲,此時的HTTP返回碼可能是200。

Origin: http://www.nczonline.net

服務器認為該請求可以接受,response Header里面就會返回Access-Control-Allow-Origin返回相同的源信息地址。

Access-Control-Allow-Origin: http://www.nczonline.net

Access-Control-Allow-Credentials:true    //是否允許發送Cookie

Access-Control-Expost-Headers:FooBar  //獲取request header里面額外的字段值

Content-Type:text/html;charset=utf-8

 

如果沒有origin信息或者信息不匹配,那么瀏覽器就駁回請求,瀏覽器的請求和響應都不包含cookie信息。

Question:為什么CORS跨域請求和響應默認不包含cookie信息?

Answer:cookie是同源共享的,既然你都跨域了,就不能使用不同域的cookie信息了。

—————————————————————————————————————

Preflighted Requests(預檢請求):

比如非簡單請求:PUT,DELETE或者Content-Type是application/json類型的請求。在正式請求之前增加一次HTTP查詢請求,稱為”預檢請求“。

OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

上面是預檢請求的HTTP requset Header參數,可以看出請求方法是OPTIONS,關鍵字Origin請求來自哪個源地址,Access-Control-Request-Method:請求方法,Access-Control-Request-Headers:逗號分隔的字符串,瀏覽器額外附加的頭部信息。

服務器收到預檢請求后,檢查origin,Access-Control-Request-Method和Access-Control-Request-Headers字段后,確認可以跨域,就返回:

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

Access-Control-Allow-Origin可以設為*,表示同意任意跨源請求。

__________________________________________________________________

一旦服務器通過了預檢請求,以后每次的正常CORS請求,跟簡單請求一樣,有Origin頭部信息字段,服務器的response header里面會有

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

頭部信息字段。

如果是非簡單請求的話,預檢之后的response header里面必包含Access-Control-Allow-Origin頭部信息。

————————————————————————————————————

CORS會通過預請求的透明服務器驗證(透明是指封閉不可見的)機制支持開發者使用自定義頭部,GET或POST之外的方法,不同類型的主體內容,預檢請求發送的是OPTIONS方法,頭部信息包含:

Origin

Access-Control-Request-Method

Access-Control-Request-Headers

發送請求后,OPTIONS預檢請求結束,再次進行真正的Response響應請求。

跨域請求默認是不帶憑證:cookie,HTTP認證和SSL證明的。但是可以通過設置:withCredentials屬性為true,指定某個請求應該發送憑證,然后服務器接受請求后,Response Header里面會返回:

Access-Control-Allow-Credentials:true

各個瀏覽器對CORS的支持程度不同,但是都支持簡單請求,可以通過檢查是否存在withCredentials屬性,IE的XDR跟XHR類似,實現安全可靠的跨域通信。所以可以先檢測withCredentials屬性,再檢測XDR對象是否存在,就可以兼顧所有瀏覽器了。

 

其他跨域技術:

圖像Ping:利用img標簽的src屬性,進行GET請求訪問,不能得到服務器的返回。適合單向通信。

JSONP:利用script標簽的src屬性,動態生成js腳本,執行服務器返回的js腳本中的帶有JSON參數的回調函數。可以通過拿到響應參數自執行回調函數,簡單有用。

 ——————————————————————————————————————————

CORS和JSONP使用目的相同,但是比JSONP更加強大,CORS主要是服務端配置好后,瀏覽器根據服務端配置的自定義頭部和提供的可以進行的CORS的方法來進行跨域操作

JSONP只支持GET請求,CORS支持所有類型的HTTP請求。

【完】

時光荏苒,如白駒過隙。
歲月如斯,然赤心如故。 

 


免責聲明!

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



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