Web安全(二)---跨域資源共享

跨域資源共享(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)。

  1. 簡單請求

只要同時滿足以下兩大條件,就屬於簡單請求。

  • 請求方法是以下三種方法之一:
    • HEAD
    • GET
    • POST
  • HTTP的頭信息不超出以下幾種字段:
    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain

凡是不同時滿足上面兩個條件,就屬於非簡單請求。

  1. 複雜請求

不滿足上面簡單的,都屬於複雜請求

#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頭信息字段。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章