HTTP之訪問控制「CORS」

CWLIN發表於2019-05-04

序言

跨域資源共享「CORS」就是在不同的域名、協議、埠直接請求資源。本文主要講述了什麼是跨域,什麼情況下會出現預檢請求,我司的跨域安全訪問

什麼是跨域

同源策略

出於安全的原因,在沒有被允許的情況下瀏覽器限制從不同源「origin」發起請求,也可能是跨站請求可以正常發起,但是返回結果被瀏覽器攔截了。

什麼才能是同源

源:由協議+域名+埠組成,也就是說,這個三個要統一才同源

例:

  • http://www.baidu.com && https://www.baidu.com 不同源 協議不同
  • http://api.baidu.com && http://www.baidu.com 不同源 域名不同
  • http://www.baidu.com:8081 && http://www.baidu.com:8080 不同源 埠不同
  • www.baidu.com/index.html && www.baidu.com/404.html 同源

什麼情況下會出現預檢請求

預檢請求

跨域資源共享標準新增了一組HTTP首部欄位,允許伺服器宣告哪些源站通過瀏覽器有許可權訪問哪些資源。在某些會對伺服器資料產生作用「需要修改資料庫」的請求「主要是GET以外的請求」,瀏覽器會先傳送通過OPTIONS方法傳送預檢請求,從伺服器那邊得到返回是否允許跨域。伺服器也可以攜帶是否需要身份憑證通知瀏覽器。

也就是說:在你傳送請求的時候,瀏覽器會自己先傳送一個預檢請求。後臺只需要識別請求的方法「OPTIONS」,然後返回一些資訊。 如下圖:

HTTP之訪問控制「CORS」
HTTP之訪問控制「CORS」
這裡有兩個login/請求,第一個是瀏覽器主動發出的。它的Request Method方法為 OPTIONS,然後伺服器的返回資訊:

  • access-control-allow-headers:允許你攜帶頭的引數
  • access-control-allow-methods:允許你傳送請求的方法
  • access-control-allow-origin:允許你傳送請求的地址

這部分資訊通知了你修改自己的請求引數來符合伺服器的要求, 伺服器如何除了瀏覽器傳送的預檢請求,可以參照這個MDN Server-Side_Access_Control (CORS)。

簡單請求

在以下情況下傳送的請求不會觸發預檢請求

  • 使用以下方法之一:「GET HEAD POST」

  • 頭部欄位在這個集合之內:「Accept, Accept-Language, Content-Language, Content-Type (需要注意額外的限制), DPR, Downlink, Save-Data, Viewport-Width, Width」

  • Content-Type以下三種之一:「text/plain,multipart/form-data,application/x-www-form-urlencoded」

  • ...

例子:我在傳送登入的時候,頭部欄位自定義了Authorization,這時候就觸發預檢請求

HTTP之訪問控制「CORS」

我司的訪問控制方式

JSON Web Token「JWT」

公司主要採用的就是JWT的跨域認證解決方案。JWT的意思就是:使用者傳送登入資訊「使用者名稱,密碼」給伺服器,伺服器認證後生成一個JSON物件,給使用者儲存,之後使用者請求資料都需要帶上JWT來傳送請求。

步驟

    1. 登入 傳送使用者名稱密碼給伺服器驗證返回JWT

HTTP之訪問控制「CORS」

    1. 前端通過LocalStorage儲存JWT

HTTP之訪問控制「CORS」

    1. 之後的請求帶上JWT
      HTTP之訪問控制「CORS」
    1. 驗證過期或者失敗直接返回401退到登入頁面
      HTTP之訪問控制「CORS」

不足之處

  • JWT一旦簽發了,在到期之前始終有效,這樣別人可以使用你的JWT獲取資料
  • JWT過期或失效的時候,使用者仍然需要通過失效的JWT請求才能知道JWT已經失效

擴充套件閱讀

如果前端沒有跟後端建立統一API設計規範,可以使用這個 RESTful api

參考

MDN HTTP訪問控制 阮一峰 JWT入門教程

相關文章