跨域判定(跨域限制是瀏覽器行爲,不是服務器行爲)

跨域限制是瀏覽器行爲,不是服務器行爲。
  瀏覽器有個同源策略,對於不同源的站點之間的相互請求會做限制。如果非同源,共有三種行爲受到限制:

  1. Cookie、LocalStorage 和 IndexDB 無法讀取。
  2. DOM 無法獲得。
  3. AJAX 請求不能發送。
      跨域限制僅僅是瀏覽器的行爲,通過代理服務器,或者其他工具發送請求就能輕鬆繞過。
跨域時的動作
瀏覽器端

假設我們點擊一個按鈕去獲取數據,獲取數據的請求準備從瀏覽器發出,這時瀏覽器先會檢測這條請求是同源還是跨域,也就是與按鈕所在頁面的地址是同源還是跨域,如果是同源,好說,直接發送出去;如果是跨域的請求,那就得hold住先,瀏覽器會在請求的http header中加上一個Origin字段,標明這個請求是從哪裏發出來的,例如: Origin:http://neighbour.com:9000

服務器端

服務器收到請求會給與響應,響應的header裏寫明跨域的配置信息,告訴瀏覽器,它允許哪些域名發來的請求訪問,哪些method可以執行。瀏覽器收到響應後自動判斷能不能真正執行請求。

是否允許跨域的判定
跨域的判斷流程

瀏覽器先根據同源策略對前端頁面和後臺交互地址做匹配,若同源,則直接發送數據請求;若不同源,則發送跨域請求。

服務器解析程序收到瀏覽器跨域請求後,根據自身配置返回對應文件頭。若未配置過任何允許跨域,則文件頭裏不包含Access-Control-Allow-origin字段,若配置過域名,則返回Access-Control-Allow-origin+ 對應配置規則裏的域名的方式

瀏覽器根據接受到的http文件頭裏的Access-Control-Allow-origin字段做匹配,若無該字段,說明不允許跨域;若有該字段,則對字段內容和當前域名做比對,如果同源,則說明可以跨域,瀏覽器發送該請求;若不同源,則說明該域名不可跨域,不發送請求。
(但是不能僅僅根據服務器返回的文件頭裏是否包含Access-Control-Allow-origin來判斷其是否允許跨域,因爲服務器端配置多域名跨域的時候,也會出現不能跨域的域名返回包裏沒有Access-Control-Allow-origin字段的情況。)
一個支持CORS的web服務器,有如下的判定字段,他們會在響應的header中寫明

  • Access-Control-Allow-Origin:允許跨域的Origin列表
  • Access-Control-Allow-Methods:允許跨域的方法列表
  • Access-Control-Allow-Headers:允許跨域的Header列表
  • Access-Control-Expose-Headers:允許暴露給JavaScript代碼的Header列表
  • Access-Control-Max-Age:最大的瀏覽器緩存時間,單位爲s

其中Access-Control-Allow-Origin(訪問控制之允許的源),在響應的http header中必須有的,表示允許訪問本服務器的源頭Origin(域名),可以是特定的域名列表,用逗號分隔,也可以是通配符 *,表示支持任意域名的訪問。
除了限定源頭Origin,還會限制請求的方法MethodHeader
如,如果服務器設定Access-Control-Allow-Methods:GET,那麼跨域的POST請求無法在這個服務器執行。

流程

1.頁面發送請求
2.瀏覽器根據同源策略做出判定,如果是同源請求,直接發送出去;如果是跨域請求,在HTTP HEADER加上Origin字段,或是先發送一次預檢請求(preflight)。
3.服務器接收請求,根據自身跨域的配置(如允許哪些域名,什麼樣的Method訪問),返回文件頭。若未配置過任何允許跨域,則文件頭裏不包含Access-Control-Allow-origin字段,若配置過域名,則返回Access-Control-Allow-origin+ 對應配置規則裏的域名的方式
瀏覽器接收到響應,根據響應頭裏的Access-Control-Allow-origin字段做匹配,如果沒有這個字段,說明不匹配;如果有,將字段內容和當前域名做比對。如匹配,則可以發送請求。

跨域的請求形式

簡單請求;非簡單請求。

簡單請求,方法僅限於 HEAD,GET或POST,且Header的字段不超過以下字段:HeadeAccept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限於三個值application/x-www-form-urlencodedmultipart/form-datatext/plain (沒有application/json, 說明如果發送JSON格式的body請求數據是一個非簡單請求)

  非簡單請求就是其他請求。簡單請求瀏覽器會直接在請求的Header加上Origin字段再發送;非簡單請求瀏覽器則會先發送一次預檢請求,根據預檢請求的結果,決定是否正式發送請求。

參考鏈接:https://segmentfault.com/a/1190000003710973#item-2-3
https://segmentfault.com/a/1190000012163420
https://juejin.im/post/5c1df8d4f265da615d72a1e4

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