CORS 跨來源資源共享完全指南

深入 CORS 與同源政策:CORS 是放寬不是防護、預檢請求、相關標頭、常見錯誤與誤區釐清

Web 安全系列之一(OWASP Top 10);最常與 CSRF 混淆,本篇徹底釐清。API 跨域場景見 API 設計範式


目錄


先搞懂同源政策(SOP)

要懂 CORS,得先懂它放寬的對象——同源政策(Same-Origin Policy, SOP)

SOP 是瀏覽器的預設安全機制一個來源的網頁,其 JavaScript 預設不能讀取另一個來源的回應。這防止惡意網站偷讀你在其他網站的資料。

你在 evil.com 的頁面,JS 想 fetch bank.com 的資料並讀回應
   → 同源政策預設擋下「讀取回應」

CORS 就是「在受控前提下,放寬這個限制」的機制。


什麼是「同源」?

「同源」= 協定(scheme)+ 主機(host)+ 埠(port)三者全相同

對照 https://app.example.com 是否同源 原因
https://app.example.com/page 三者相同(路徑不影響)
http://app.example.com 協定不同
https://api.example.com 主機不同(子網域也算)
https://app.example.com:8080 埠不同

任一不同就是「跨來源(cross-origin)」,預設受 SOP 限制。


什麼是 CORS?

CORS(Cross-Origin Resource Sharing,跨來源資源共享) 是一套**伺服器透過 HTTP 標頭,告訴瀏覽器「允許哪些來源讀取我的回應」**的機制。

瀏覽器:我(app.example.com)想讀 api.other.com 的回應
api.other.com 回應帶: Access-Control-Allow-Origin: https://app.example.com
   → 瀏覽器看到「我在允許名單內」→ 放行 JS 讀取回應
   → 否則 → 擋下,console 報 CORS 錯誤

關鍵:是伺服器用標頭「授權」,瀏覽器「執行」這個授權。


CORS 怎麼運作

簡單請求(Simple Request)

符合特定條件的請求(如 GET/POST、簡單標頭、特定 Content-Type)直接送出,瀏覽器再依回應的 Access-Control-Allow-Origin 決定是否讓 JS 讀回應:

GET /data HTTP/1.1
Origin: https://app.example.com

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://app.example.com   ← 伺服器授權
  • 標頭符合 → JS 能讀回應
  • 不符合 → 請求其實已送達伺服器、伺服器也處理了,但瀏覽器擋住 JS 讀取回應,並在 console 報錯

重點:CORS 擋的是「JS 讀回應」,不是「請求不發出」。這點對理解「CORS 不防 CSRF」很關鍵。


預檢請求(Preflight)

對「可能有副作用」的請求(如 PUT/DELETE、自訂標頭、特殊 Content-Type),瀏覽器會先送一個 OPTIONS 預檢問伺服器准不准,准了才送真正的請求:

OPTIONS /data HTTP/1.1            ← 預檢
Origin: https://app.example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Authorization

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: PUT, POST, DELETE
Access-Control-Allow-Headers: Authorization
Access-Control-Max-Age: 86400     ← 預檢結果可快取多久
  • 預檢通過 → 才送真正的 PUT
  • Access-Control-Max-Age 讓瀏覽器快取預檢結果,避免每次都先 OPTIONS

相關標頭

標頭(回應) 作用
Access-Control-Allow-Origin 允許哪個來源讀回應(具體來源或 *
Access-Control-Allow-Methods 允許的 HTTP 方法(預檢用)
Access-Control-Allow-Headers 允許的自訂請求標頭(預檢用)
Access-Control-Allow-Credentials 是否允許帶憑證(cookie)
Access-Control-Max-Age 預檢結果可快取秒數
Access-Control-Expose-Headers 允許 JS 讀取哪些回應標頭
標頭(請求) 作用
Origin 瀏覽器自動帶上的發起來源(不可由 JS 偽造)

憑證與萬用字元的陷阱

要在跨來源請求帶 cookie/憑證credentials: 'include')時,有嚴格限制:

Access-Control-Allow-Origin: *               ← ❌ 帶憑證時「不允許」用萬用字元
Access-Control-Allow-Credentials: true
  • 帶憑證時,Access-Control-Allow-Origin 必須是具體來源,不能是 *,且要加 Access-Control-Allow-Credentials: true
  • 這是安全設計:避免「任意網站 + 自動帶 cookie」讀走你的資料

設定 CORS 時別圖方便用 * + credentials——瀏覽器會直接拒絕;正確做法是動態回填已驗證白名單內的具體 Origin


關鍵釐清:CORS 是放寬,不是防護

這是最多人誤解的地方,務必記住:

誤解 事實
「CORS 是保護我 API 的安全機制」 CORS 是放寬同源限制的機制,本身不「保護」伺服器
「設了 CORS 就能擋壞人」 CORS 只在瀏覽器生效;curl、server-to-server、Postman 完全不受 CORS 限制
「CORS 能防 CSRF」 不能。CSRF 不需要讀回應;CORS 管的正是「能不能讀回應」(見 CSRF
「CORS 錯誤代表請求被擋下」 請求多半已送達伺服器並執行,只是瀏覽器擋住 JS 讀取回應
CORS 管:瀏覽器中的 JS「能不能讀跨來源回應」
CORS 不管:請求發不發得出去、伺服器收不收、非瀏覽器客戶端
真正的存取控制:靠伺服器端的認證/授權(見 OWASP A01、認證與授權)

一句話:CORS 是「我允許誰來讀我」,不是「我擋住壞人」。 伺服器安全要靠認證授權,不是 CORS。


常見誤區

1. 「被 CORS 擋了 = 我的 API 安全」

完全相反。CORS 錯誤只代表瀏覽器不讓那個前端讀回應;攻擊者用非瀏覽器工具直接打你 API 不受任何 CORS 影響。安全要靠認證/授權。

2. 「前端報 CORS 錯,改前端就好」

CORS 由伺服器回應標頭決定,前端改不了。要在伺服器設正確的 Access-Control-Allow-*

3. 「一律設 Access-Control-Allow-Origin: * 最省事」

公開唯讀 API 也許可以,但需要帶 cookie 的 API 不能用 *,且全開放可能讓任意網站讀取本應受限的資料。應回填白名單內的具體來源。

4. 「CORS 能防 CSRF」

不能。兩者是不同問題:CORS 管「讀回應」,CSRF 是「偽造會產生副作用的請求」。防 CSRF 用 SameSite/token(見 CSRF)。


常見問題

問題 1:CORS 到底是放寬還是限制?

放寬。預設的同源政策才是限制;CORS 是伺服器用標頭選擇性放寬「允許哪些來源讀我的回應」。

問題 2:為什麼會出現「blocked by CORS policy」?

你的前端(某來源)想讀另一來源的回應,但對方回應沒有(或不符)Access-Control-Allow-Origin瀏覽器因而擋住 JS 讀取。請求通常已送達伺服器。

問題 3:CORS 錯誤要改前端還後端?

後端——CORS 由伺服器回應標頭控制。前端無法靠自己「關掉」CORS(開發時頂多用代理繞過)。

問題 4:CORS 能保護我的 API 嗎?

不能當成保護。CORS 只在瀏覽器生效,非瀏覽器客戶端(curl/server)不受限。真正的保護靠伺服器端認證與授權(OWASP A01)。

問題 5:為什麼有時會先送一個 OPTIONS?

那是預檢請求。對可能有副作用的跨來源請求(PUT/DELETE、自訂標頭等),瀏覽器先用 OPTIONS 問伺服器准不准,通過後才送真正請求。


總結

核心要點

  • 同源政策(SOP) 是預設限制:JS 不能讀跨來源回應;同源 = 協定+主機+埠全同
  • CORS 是「放寬」SOP 的機制:伺服器用標頭授權哪些來源可讀回應,瀏覽器執行
  • 流程:簡單請求直接送;有副作用的先送 OPTIONS 預檢
  • 帶 cookie 時 Allow-Origin 不能用 *,要具體來源 + Allow-Credentials
  • CORS 是放寬不是防護:只在瀏覽器生效、不防 CSRF、非瀏覽器不受限;安全靠認證授權
  • CORS 錯誤改後端標頭,且請求多半已送達

快速參考

概念 重點
同源 協定 + 主機 + 埠 全相同
SOP 預設:不能讀跨來源回應
CORS 伺服器授權放寬讀取
預檢 有副作用請求先送 OPTIONS
帶憑證 Allow-Origin 不可用 *
本質 放寬「能不能讀」,安全防護

建立日期:2026-06-18

🔗相關文章