CORS:瀏覽器為什麼擋你的請求
情境:最讓初學者抓狂的錯誤訊息
你的電商前端(https://shop.example.com)要呼叫一個商品 API(https://api.products.com),程式碼看起來完全正確,但瀏覽器 Console 出現這個紅色錯誤:
Access to fetch at 'https://api.products.com/products' from origin
'https://shop.example.com' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
明明用 Postman 測試完全沒問題,為什麼瀏覽器就是不行?
同源政策:公寓大樓的安全規定
什麼是「同源」(Same Origin)?
「源」(Origin)= 通訊協定 + 網域 + 埠號
| 網址 | 是否同源(和 https://shop.example.com) |
|---|---|
https://shop.example.com/orders | ✅ 同源(只是路徑不同) |
https://api.example.com/products | ❌ 不同源(子網域不同) |
http://shop.example.com | ❌ 不同源(協定不同,http vs https) |
https://shop.example.com:8080 | ❌ 不同源(埠號不同) |
https://other-shop.com | ❌ 不同源(網域不同) |
公寓大樓比喻
把每個網域想成一棟公寓大樓:
shop.example.com是 A 棟api.products.com是 B 棟
同源政策的規定:A 棟的住戶(瀏覽器中的網頁)不能直接跑去 B 棟拿東西,除非 B 棟的管理員(伺服器)說「A 棟的人可以來」。
這個規定是瀏覽器的安全保護,防止惡意網站偷偷存取你在其他網站的資料。
CORS 是什麼?
CORS(Cross-Origin Resource Sharing)跨來源資源共享 = B 棟管理員貼在門口的「訪客規定」。
如果 B 棟(API 伺服器)的回應 Header 裡有這個:
Access-Control-Allow-Origin: https://shop.example.com
那瀏覽器就會說:「好,這個 API 允許 shop.example.com 來存取,放行。」
如果沒有這個 Header,瀏覽器就擋下來。
Preflight Request:先問再進
當你的 API 請求比較複雜(比如帶了自訂 Header 或用 POST/PUT/DELETE),瀏覽器不會直接送請求,而是先送一個「探路」的請求:
瀏覽器背後實際做的事:
步驟 1:先送 OPTIONS 請求(Preflight)
OPTIONS https://api.products.com/orders
Origin: https://shop.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Authorization, Content-Type
步驟 2:API 回應「允許了什麼」
Access-Control-Allow-Origin: https://shop.example.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Authorization, Content-Type
步驟 3:瀏覽器確認可以,才送真正的 POST 請求
這就是為什麼有時候你會在 Network 面板看到兩個請求,一個 OPTIONS 一個 POST。
常見錯誤與修法
錯誤 1:API 完全沒設 CORS Header
錯誤訊息:No 'Access-Control-Allow-Origin' header is present
修法:在 API 伺服器加上 CORS Header(後端的工作)
錯誤 2:CORS 設定太寬鬆
用 * 允許所有來源看起來很方便,但如果你的 API 需要帶 Cookie 或 Authorization,* 是無效的,必須指定具體來源。
錯誤 3:忘了 Preflight 的回應
如果你的 API 有處理 POST 但沒有處理 OPTIONS,Preflight 就會失敗,導致所有複雜請求都被擋下。
重要觀念:CORS 是瀏覽器的機制
Postman 測試沒問題,瀏覽器卻報 CORS 錯誤——這很正常,因為:
CORS 是瀏覽器的安全機制,不是 API 伺服器的機制。
Postman 不是瀏覽器,不受同源政策限制。API 伺服器收到請求是沒問題的,只是瀏覽器在收到回應後,發現沒有被授權的 Header,就把回應擋掉了。
所以解決 CORS 問題,通常要在 API 伺服器端加設定,不是在前端加。
練習題
AI 協作:學了這個,跟 AI 怎麼配合?
理解 CORS 的原理,讓你在遇到 CORS 錯誤時能準確描述問題,AI 就能給出正確的修法。
你的人類優勢:
- 你知道前端部署在哪個網域、要呼叫哪個 API 網域
- 你能判斷這個 API 是你們自己控制的(可以改 CORS 設定)還是第三方的(只能繞道)
可以這樣跟 AI 說:
我的前端部署在 https://shop.example.com,要呼叫部署在 https://api.example.com 的 Node.js Express API。瀏覽器報 CORS 錯誤。請幫我在 Express 後端加上正確的 CORS 設定:只允許 shop.example.com 這個來源,需要支援 POST 請求和 Authorization Header。
互動示範
挑戰任務
以下哪個情況會觸發 CORS 錯誤? A) 前端在 https://shop.example.com,呼叫 https://shop.example.com/api/orders B) 前端在 https://shop.example.com,呼叫 https://api.orders.com/orders C) 用 Postman 呼叫 https://api.orders.com/orders 請輸入正確答案字母。
CORS 錯誤要修,通常是修哪一側的程式碼? A) 前端(React/JS) B) 後端(API 伺服器) C) 兩者都要改 請輸入答案字母。
為什麼不建議把 CORS 設成 Access-Control-Allow-Origin: * ?請說明風險。