記得我第一次正式的串接API的時候,踏著愉悅的心想說自己要成為一個真正的前端要來串接了~~~ 結果寫了對應的程式打API之後,資料沒有出來,還馬上在console裏收到一個紅紅的錯
這個問題通常因為放到正式環境又沒問題了,或者直接拍出大絕請後端開好開滿,把
Access-Control-Allow-Origin: *
設定完成,幾乎就解決問題了~
沒錯,如果你只想30秒解決這個問題,告訴你一個快速的結論:
請後端工程師,在API的header加上這個設定屬性
Access-Control-Allow-Origin: *
但只要這樣就夠了嗎?身為一個追根究底的工程師,我們應該知道為什麼會有這個問題吧!或是如果在本機開發遇到這個狀況該怎麼處理?或是知道之後才方便之後被面試問到的時候不會答不出來吧(?)
好啦,有這麼多理由該知道,那我們就開始吧!
從錯誤訊息出發
其實錯誤訊息裡就告訴你為什麼了
access to XMLHttpRequest at 連結A from origin 連結B has been blocked by CORS policy: response to preflight request doesn't pass access control check: No 'Access-control-allow-origin' header is present on the requested resource
當你要從連結B要request到連結A時,被CORS的政策擋下來了,冒號後面告訴你原因:因為preflight request沒有通過存取檢測,請檢查看看request的來源的header有沒有access-control-allow-origin。
實務上就是我的前台網站在 連結A 但需要透過API 連結B 時,前後台兩者網址不同來源,但前台要取得不同來源的資料時,若沒有做好相關的設定就會出現上面的錯誤
錯誤訊息好像每個字都看得懂,但CORS是什麼意思?又為什麼要有CORS? header要加的這個又是什麼呢?接下來讓我們繼續看下去~
Same Origin Policy (同源政策)
在開始CORS之前,我們需要先知道瀏覽器的Same Origin Policy(同源政策)。
瀏覽器基於
安全性
的考量,規定當你的網站要呼叫API時,需要是同一個來源。
如果是不同來源,瀏覽器依然會幫你發出request,但會把收到的response阻擋起來不給你的網站。
那什麼叫同一個來源呢?
同源(Same-Origin)? 跨來源(Cross-Origin)? 來源怎麼判定?
當兩個網址的 schema(protocol) + host + port 皆相同,就是同源(Same-Origin),只要有一者不同,就是跨來源(Cross-origin)
以下舉幾個範例:
了解了同源、跨來源後,你應該接下來馬上會想到... 怎麼可能我要打的API都是同一個來源呢?如果就是不同源該則麼辦?
所以我們需要CORS! 什麼是CORS?
CORS = 跨來源資源共用(Cross-Origin Resource Sharing (CORS))。
跨來源資源共用 : 發出request的來源不同,但需要共用資源
可以把API request想像成大樓裡的一個個部門辦公室,有各自的門禁卡。資訊部的人不能進到行銷部,因為他們是不同來源。那如果最近資訊部跟行銷部密切合作,希望可以讓資訊部的人直接進到行銷部怎麼辦?這時候瀏覽器就是這個開啟門禁卡權限的管理員,要開啟門禁權限的方法就是CORS
這邊我們要注意一點,門禁權限是瀏覽器訂的,意思是如果今天管理員換人了,不是瀏覽器了,那部門之間的門禁就消失了,就不會有不同來源會被阻擋下來的問題(所以你有發現嗎
我們用postman打API的時候,就不會看到CORS的問題,因為管理員是postman不是瀏覽器了!)
CORS的運作原理
簡單來說,要開啟不同來共享資源的方式就是:透過在API的response中加入新的http header讓瀏覽器透過這些資訊,來決定要不要放行這個response。
我們已經簡單的知道為什麼我們會遇到這個問題了,那要怎麼加上新的http header當作跨來源的通行證? 又詳細的運作原理是什麼呢?待明天揭曉~
CORS 完全手冊:為什麼會發生 CORS 錯誤?
https://blog.huli.tw/2021/02/19/cors-guide-1/
MDN - CORS
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS