Share This Post

介紹

CORS (Cross-Origin Resource Sharing),中文為「跨來源資源共用」,主要出現在於網頁引用不同來源的資料時產生的錯誤。

當網頁使用 HTMLHttpRequest、Fetch、Axios 發起不是目前來源的請求時,會建立一個跨來源 HTTP 請求(cross-origin HTTP request),但基於同源政策 (same-origin policy) 的安全性考量,送出的跨來源 HTTP 請求會受到限制,進而出現 CORS 的錯誤。

cors_principle.png

Host、Referer、Origin 的區別

Host

此請求將送往哪裡,主要代表「域名+端口」。瀏覽器發起 HTTP 請求時會帶有此 HEADER。

Origin

從哪個網域傳送而出(跨域),主要由「協議+域名+端口」。用於 CORS 請求、同域的「POST」。

Referer

來自哪個網域,主要由「協議+域名+端口+路徑+參數」。當前請求的來源頁面的地址,服務端一般使用 Referer 首部作為訪問來源,以此進行「統計分析」、「日誌紀錄」、「暫存優化」等。

一般情况下瀏覽器會帶此 HEADER,但下列情況不會帶有

  • 來源頁面協議為 File 或 Data URI(例如:頁面從本地打開的)
  • 來源頁面是 HTTPS,而目標 URL 是 HTTP
  • 瀏覽器地址欄直接輸入網址訪問
  • 通过瀏覽器書籤直接訪問
  • 使用 JS 的 location.href 跳轉

Origin 與 Referer 比較

  • 只有「跨域请求同域發送 POST」請求時,才會攜帶 origin;而 Referer只要能被瀏覽器獲取都會攜帶,除了上面的情況外
  • 若瀏覽器不能獲取請求源頁面網址,Referer 不會放入 HEADER 中,但 Origin 依舊會發送,但值是 null 而已(註:雖值為 null,但此請求依舊屬於 CORS 請求)
  • Origin 的值只包括**「協議」、「域名」、「端口」,而 Rerferer 不但包括「協議」、「域名」、「端口」、「路徑」、「參數」,但**不包括 hash 值

CORS 預檢(簡單請求)

在發起跨來源資源共用的請求時,通常會發起 CORS 預檢 來驗證是否能夠取得相關資源,若是無法取得,就會避免正式請求的發起,以避免資源的浪費。

部分不受同源政策限制的情況

  • 跨來源寫入
    • 鏈結 <a>
    • 重新導向
    • 表單提交
  • 嵌入
    • <script> 嵌入腳本
    • <link rel=”stylesheet” href=“…”> 嵌入 CSS
    • <img> <video> <audio> 等等嵌入資源
    • 通過 <iframe> 載入資源

⛔ 一般而言,跨域讀取是不被允許的。包括讀取 request 中的 res

如何允許不同源的網站訪問

跨域讀操作一般是不被允许的,而這種情况是我们開發過程中最關心、最常見的情況,因此必須解决。可以使用 CORS 來允許跨域訪問。CORS 是 HTTP 的一部分,它允許伺服器指定那些主機可以從這個伺服器加載資料。

若想實現 CORS 機制的跨域請求,是需要瀏覽器與伺服器同時支援。關於瀏覽器對 CORS 的支援情況,再加上 CORS 整個過程都是由瀏覽器自動完成的,因此前端無需做任何設置

為何需要 CORS 跨域訪問

随著 Web 開放的程度越來越高,頁面的內容也越來越豐富。為了分而治之,頁面中的内容可能來自不同地方,因此必然會通過 API 進行跨域訪問。CORS(Cross-Origin Resource Sharing)由 W3C 於 2009/03/17 編寫工作草案,直到 2014/01/16 才正式成为行業規範,所有瀏覽器得以遵守

CORS 工作原理

  1. 若瀏覽器發送跨域請求,HTTP 請求的 HEADER 就會攜帶 Origin 表明自己的位置
  2. 伺服器收到請求後,就可以根據傳過來的 Origin 值做邏輯判斷,決定是否要共享資源給此網站。這個決定將透過 Res HEADER 的「**Access-Control-Allow-Origin」**來乘載,它的 value 可以是任意值,如下情况:
    • 值為「*」通配符,允许所有的 Origin 共享此資源
    • 值與 Origin「相同」,則共享给此 Origin
    • 值與 Origin「不相同」,則不共享给此 Origin
    • 無此標頭,則不共享给此 Origin
  3. 瀏覽器收到 Response 後,會去提取「Access-Control-Allow-Origin」的值,然後根據上述的規則來決定是否要接收此響應的內容

CORS 細微操控(授權響應 HEADER)

在 CORS 規範中,除了可以通过「**Access-Control-Allow-Origin」**響應頭來對主體資源(URL)進行授權外,還提供了針對具體響應頭更精細的控制,這個 Res 的 HEADER 就是「Access-Control-Expose-Headers」。換句話講,該值用於規定那些 Res HEADER 可以暴露給前端,預設情況下以下 6 種 Res HEADER 無需特別的顯示指定就會支持:

  • Cache-Control
  • Content-Language
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

若不在此值裡面的頭,則瀏覽器讓其對前端不可見,對 JavaScript 也不可見。

但是,這種精細控制 HEADER 的機制對於簡單請求是無效的,只針對非簡單請求(複雜請求)。由此可見,將哪些類型的跨域資源請求劃分為簡單請求的範疇就特別重要。

Ref

訂閱研究文章

Get updates and learn from the best

More To Explore

Scroll to Top

hurry up !

軟體工程師培訓

限時免費報名中

藉由與「真實世界軟體專案」相同的技術、工具與開發流程,化簡成與商業機密無關、門檻較低更容易上手的「模擬專案」,讓你有機會在職場前輩的陪伴下,完成真槍實彈的練習,動手解決真實的問題,快速累積個人的經驗與作品,而不只是「學習技術」而已。