跨域資源共享(CORS)
#1 什麼是CORS
CORS是一個W3C標準,全稱是"跨域資源共享"(Cross-origin resource sharing)。
它允許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。
整個CORS通信過程,都是瀏覽器自動完成,不需要用戶參與。對於開發者來說,CORS通信與同源的AJAX通信沒有差別,代碼完全一樣。瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感覺。
因此,實現CORS通信的關鍵是服務器。只要服務器實現了CORS接口,就可以跨源通信。
#2 兩種請求
瀏覽器將CORS請求分成兩類:簡單請求(simple request)和非簡單請求(not-so-simple request)。
- 簡單請求
只要同時滿足以下兩大條件,就屬於簡單請求。
- 請求方法是以下三種方法之一:
- HEAD
- GET
- POST
- HTTP的頭信息不超出以下幾種字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain
凡是不同時滿足上面兩個條件,就屬於非簡單請求。
- 複雜請求
不滿足上面簡單的,都屬於複雜請求
#3 請求過程
#3.1 簡單請求
當瀏覽器發現跨域的Ajax請求時簡單請求,會走如下流程 :
- 瀏覽器 : 兄弟,你這是需要跨域請求吧 ! 得問一下服務器大哥同不同意吧, 我在你的header里加上Origin信息, 讓服務器大哥知道你是哪來的
- 服務器 : 來者何人,亮出你的Origin給我瞧瞧(服務器大哥拿着Origin和自己手上的Origin比較),在我的允許範圍內,允許進入服務器
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-aKvZLMX8-1584912081477)(https://raw.githubusercontent.com/Coxhuang/yosoro/master/20200323031039.png)]
服務器配置CORS
//指定允許其他域名訪問
'Access-Control-Allow-Origin:http://admin.minhung.me:19700'//一般用法(*,指定域,動態設置),3是因爲*不允許攜帶認證頭和cookies
//是否允許後續請求攜帶認證信息(cookies),該值只能是true,否則不返回
'Access-Control-Allow-Credentials:true'
Access-Control-Allow-Origin有多種設置方法 :
- 設置是最簡單粗暴的,但是服務器出於安全考慮,肯定不會這麼幹,而且,如果是的話,遊覽器將不會發送cookies,即使你的XHR設置了withCredentials
- 動態設置爲請求域,多人協作時,多個前端對接一個後端,這樣很方便
#3.2 複雜請求
最常見的情況爲,當我們使用PUT
或者DELETE
請求時,瀏覽器會先發送option
(預檢)請求
與簡單請求不同的是,option請求多了2個字段:
- Access-Control-Request-Method:該字段是必須的,用來列出瀏覽器的CORS請求會用到哪些HTTP方法。
- Access-Control-Request-Headers:該字段是一個逗號分隔的字符串,指定瀏覽器CORS請求會額外發送的頭信息字段
Access-Control-Request-Method,Access-Control-Request-Headers返回的是滿足服務器要求的所有請求方式,請求頭,不限於該次請求,服務器收到"預檢"請求以後,檢查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以後,確認允許跨源請求,就可以做出迴應。
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://api.minhung.me:19800
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
上面的HTTP迴應中,關鍵的是Access-Control-Allow-Origin字段,表示http://api.minhung.me:19800可以請求數據。該字段也可以設爲星號,表示同意任意跨源請求。
如果瀏覽器否定了"預檢"請求,會返回一個正常的HTTP迴應,但是沒有任何CORS相關的頭信息字段。這時,瀏覽器就會認定,服務器不同意預檢請求,因此觸發一個錯誤,被XMLHttpRequest對象的onerror回調函數捕獲。控制檯會打印出如下的報錯信息。
一旦服務器通過了"預檢"請求,以後每次瀏覽器正常的CORS請求,就都跟簡單請求一樣,會有一個Origin頭信息字段。服務器的迴應,也都會有一個Access-Control-Allow-Origin頭信息字段。