CORS 跨域詳解

1、爲何會有跨域問題

  • 瀏覽器同源策略
  • (跨域是瀏覽器的限制,抓包工具等能夠拿到數據)
  • 瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感受
  • 如下狀況會致使跨域


    2、如何解決跨域

  • CORS(跨域資源共享),支持全部類型的 http 請求,本文主要介紹這種方式

3、簡單請求和非簡單請求

Ajax 按照條件能夠分爲兩種請求方式,簡單請求和非簡單請求。nginx

同時知足如下兩個條件,就屬於簡單請求
ajax

  1. 使用下列方法之一
    • head
    • get
    • post
  2. 請求的header是
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type 只限於三個值
      • application/x-www-form-urlencodes
      • multipart/form-data
      • text/plain

對於簡單請求,瀏覽器直接發出CORS請求。在頭部字段中,增長一個Origin字段。(chrome有時會隱藏這個字段)
chrome

下面是一個項目中的ajax封裝,使用的就是簡單請求:json


4、CORS請求相關的字段,都以 Access-Control- 開頭

  • Access-Control-Allow-Origin :必選
    • (一個或者多個容許跨越的)請求頭Origin字段的值
    • *:接受任何域名
  • Access-Control-Allow-Credentials: 可選
    • true:表示容許發送cookie,此時 Access-Control-Allow-Origin 不能設置爲*,必須指定明確的,與請求網頁一致的域名;
    • 不設置該字段,不須要瀏覽器發送cookie
  • Access-Control-Expose-Headers:可選
    • 列出了哪些首部能夠做爲響應的一部分暴露給外部
    • 默認,只有六種暴露給外部
      • Cache-Control
      • Content-Language
      • Content-Type
      • Expires
      • Last-Modified
      • Pragma
    • 若是想讓客戶端能夠訪問到其餘的首部信息,能夠將他們在Access-Control-Expose-Headers裏面列出來

5、withCredentials 屬性

  • CORS默認不發送Cookie和HTTP認證信息,若是要把Cookie 發送到服務器,一方面須要服務器贊成,設置響應頭 Access-Control-Allow-Credentials:true另外一方面,客戶端發送請求時,也要進行一些設置,例如 xhr.withCredentials = true;

6、非簡單請求

非簡單請求就是那種對服務器有特殊要求的請求,好比請求方法爲PUT 或者 DELETE,或者 Content-Type 爲 application/json;跨域

預檢請求和迴應

非簡單請求的CORS請求,會在正式通訊以前,增長一次HTTP查詢請求,稱爲「預檢」。瀏覽器會詢問服務器,當前網頁所在的域名是否在服務器的許可名單以內,以及可使用哪些 HTTP 動詞和頭部信息段,只有獲得確定答覆,纔會發出正式的接口請求。不然,報錯。瀏覽器

一、預檢請求服務器

  • 用 OPTIONS 方法,詢問。預檢請求包括三個字段
    • Origin,表示請求來自哪一個域;
    • Access-Control-Request-Method:必須,瀏覽器會使用的請求方法;
    • Access-Control-Request-Headers: 瀏覽器發送 CORS 請求會額外發送的頭部信息段;

二、預檢迴應cookie

  • 服務器收到預檢請求後,檢查了Origin,Access-Control-Request-Method,Access-Control-Request-Headers字段後,確認容許跨域,就能夠作出迴應
  • 若是瀏覽器否定了「預檢」請求,會返回一個正常的HTTP迴應,可是沒有任何CORS相關的頭部信息字段,瀏覽器會認爲不一樣意,觸發一個錯誤
  • 服務器迴應的其餘CORS字段
    • Access-Control-Allow-Methods: 必需,逗號分隔的字符串,表示服務器支持的全部跨域請求方法;
    • Access-Control-Allow-Headers:瀏覽器支持的全部頭部字段;
    • Access-Control-Allow-Credentials:Cookie
    • Access-Control-Allow-Max-Age: 指定本次請求的有效期;

正常請求和迴應

一旦經過預檢請求,之後就跟簡單請求同樣。app

另外一個項目使用了這種方式,如下是其截圖:工具




7、服務端如何設置CORS

  • 若是設置請求頭 Content-Type:application/x-www-form-urlencoded,則爲簡單請求
    • 直接設置響應頭 Access-Control-Allow-Origin 爲 *,或者具體的域名;
    • 若是響應頭Access-Control-Allow-Credentials 爲 true,則此時Access-Control-Allow-Origin 不能設置爲*,必須指定明確的域名;
  • 若是設置請求頭 Content-Type:application/json,則爲非簡單請求
    • 處理 OPTIONS 請求,服務端能夠單獨寫一個路由
    • 能夠把這部分抽離處理,做爲一箇中間件,例如Koa;
相關文章
相關標籤/搜索