關於跨域的深刻理解

跨域資源共享(cros)是一種機制它使用額外的 HTTP 頭來告訴瀏覽器 讓運行在一個 origin (domain) 上的Web應用被准許訪問來自不一樣源服務器上的指定的資源。當一個資源從與該資源自己所在的服務器不一樣的域、協議或端口請求一個資源時,資源會發起一個跨域 HTTP 請求。html

(即便是同一個域不一樣端口的請求也算是跨域行爲)前端

參考資料 MDN相關資料參考阮老師博客資料參考跨域

實際場景

這裏,咱們使用三個場景來解釋跨域資源共享機制的工做原理。這些例子都使用 XMLHttpRequest 對象。(對於fetch請求也是大體相同的機理)瀏覽器

簡單請求

某些請求不會觸發 CORS 預檢請求。本文稱這樣的請求爲「簡單請求」,請注意,該術語並不屬於 Fetch (其中定義了 CORS)規範。若請求知足全部下述條件,則該請求可視爲「簡單請求」:緩存

  • 使用下列方法之一:
    • GET
    • HEAD
    • POST
  • Fetch 規範定義了對 CORS 安全的首部字段集合,不得人爲設置該集合以外的其餘首部字段。該集合爲:
    • 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
  • 請求中的任意XMLHttpRequestUpload 對象均沒有註冊任何事件監聽器;XMLHttpRequestUpload 對象可使用 XMLHttpRequest.upload 屬性訪問。
  • 請求中沒有使用 ReadableStream 對象。

預檢請求

與前述簡單請求不一樣,「需預檢的請求」要求必須首先使用 OPTIONS 方法發起一個預檢請求到服務器,以獲知服務器是否容許該實際請求。"預檢請求「的使用,能夠避免跨域請求對服務器的用戶數據產生未預期的影響。安全

當請求知足下述任一條件時,即應首先發送預檢請求:服務器

  • 使用了下面任一 HTTP 方法:
    • PUT
    • DELETE
    • CONNECT
    • OPTIONS
    • TRACE
    • PATCH
  • 人爲設置了對 CORS 安全的首部字段集合以外的其餘首部字段。該集合爲:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type (須要注意額外的限制)
    • DPR
    • Downlink
    • Save-Data
    • Viewport-Width
    • Width
  • Content-Type 的值不屬於下列之一:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain
  • 請求中的XMLHttpRequestUpload 對象註冊了任意多個事件監聽器。
  • 請求中使用了ReadableStream對象。

附帶身份憑證的請求

Fetch 與 CORS 的一個有趣的特性是,能夠基於 HTTP cookies 和 HTTP 認證信息發送身份憑證。通常而言,對於跨域 XMLHttpRequest 或 Fetch 請求,瀏覽器不會發送身份憑證信息。若是要發送憑證信息,須要設置 XMLHttpRequest 的某個特殊標誌位。cookie

  1. 請求配置需添加 withCredentials 標誌設置爲 true
  2. 服務器端的響應中設置響應頭 Access-Control-Allow-Credentials: true

!!!!app

附帶身份憑證的請求與通配符

對於附帶身份憑證的請求,服務器不得設置 Access-Control-Allow-Origin 的值爲「*」。cors

這是由於請求的首部中攜帶了 Cookie 信息,若是 Access-Control-Allow-Origin 的值爲「*」,請求將會失敗。而將 Access-Control-Allow-Origin 的值設置爲 foo.example,則請求將成功執行。

另外,響應首部中也攜帶了 Set-Cookie 字段,嘗試對 Cookie 進行修改。若是操做失敗,將會拋出異常。

響應首部字段

響應首部的字段是須要手動設置的。

Access-Control-Allow-Origin

響應首部中能夠攜帶一個 Access-Control-Allow-Origin 字段,其語法以下: Access-Control-Allow-Origin: <origin> | *

Access-Control-Expose-Headers

Access-Control-Expose-Headers 頭讓服務器把容許瀏覽器訪問的頭放入白名單,例如: Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header

Access-Control-Max-Age

Access-Control-Max-Age 頭指定了preflight請求的結果可以被緩存多久 Access-Control-Max-Age: <delta-seconds>

Access-Control-Allow-Credentials

Access-Control-Allow-Credentials 頭指定了當瀏覽器的credentials設置爲true時是否容許瀏覽器讀取response的內容。當用在對preflight預檢測請求的響應中時,它指定了實際的請求是否可使用credentials。請注意:簡單 GET 請求不會被預檢;若是對此類請求的響應中不包含該字段,這個響應將被忽略掉,而且瀏覽器也不會將相應內容返回給網頁 Access-Control-Allow-Credentials: true

Access-Control-Allow-Methods

Access-Control-Allow-Methods 首部字段用於預檢請求的響應。其指明瞭實際請求所容許使用的 HTTP 方法。 Access-Control-Allow-Methods: <method>[, <method>]*

Access-Control-Allow-Headers

Access-Control-Allow-Headers 首部字段用於預檢請求的響應。其指明瞭實際請求中容許攜帶的首部字段。 Access-Control-Allow-Headers: <field-name>[, <field-name>]*

HTTP 請求首部字段

本節列出了可用於發起跨域請求的首部字段。請注意,這些首部字段無須手動設置。 當開發者使用 XMLHttpRequest 對象發起跨域請求時,它們已經被設置就緒。

Origin

Origin 首部字段代表預檢請求或實際請求的源站 Origin: <origin>

Access-Control-Request-Method

Access-Control-Request-Method 首部字段用於預檢請求。其做用是,將實際請求所使用的 HTTP 方法告訴服務器。 Access-Control-Request-Method: <method>

Access-Control-Request-Headers

Access-Control-Request-Headers 首部字段用於預檢請求。其做用是,將實際請求所攜帶的首部字段告訴服務器。 Access-Control-Request-Headers: <field-name>[, <field-name>]*

福利放送 免費分享【精品付費課程透析HTTP協議】

網盤地址: pan.baidu.com/s/1aMOpoed8…

掃描下方二維碼關注公衆號 【前端每天見】 獲取課程提取碼

相關文章
相關標籤/搜索