# CORS ## CORS (Cross-Origin Resource Sharing) [參考系列文](https://blog.huli.tw/2021/02/19/cors-guide-1/) <= 幾乎從這看的三手整理資訊 [ref2](https://shubo.io/what-is-cors/) ### 理解 CORS (Cross-Origin Resource Sharing) 是針對不同源的請求而定的規範,透過 JavaScript 存取非同源資源時,server 必須明確告知瀏覽器允許何種請求,只有 server 允許的請求能夠被瀏覽器實際發送,否則會失敗。 瀏覽器的同源政策([Same-origin policy](https://developer.mozilla.org/zh-TW/docs/Web/Security/Same-origin_policy)),因為安全性問題的關係,只在瀏覽器這個執行環境(runtime)上才有的限制,實際上他擋的是回來的 response 而 requset 還是有發出去,server 還是有接收到請求 ### 何謂同源 相同的 protocol + domain + port (協定 + 網域 + 埠號) ### 如何解決 CORS (簡單請求) 1. 關閉瀏覽器的安全性設置,進到瀏覽器內容更改目標輸入欄位加上 `--disable-web-security --user-data-dir=C:\Program Files (x86)\Google\Chrome\Application` 不過這只是自己電腦開發時有用的爛招 2. 如果跟想存取資源的後端有合作關係的話,請後端在 response header 加上 `Access-Control-Allow-Origin` 就可以了( * 允許任何 requset 存取)( * = wildcard ) 3. proxy server,直接透或代理 server 來脫離瀏覽器的限制,讓 server 去請求資源,然後再回給瀏覽器,此時就可以自己在 server 加讓第二點的 header 來取得資源 總結就是根本上要在 reponse 加上第二點的 header,來允許發出 request 的 origin 能夠真的接收到 reponse ### 簡單請求與非簡單請求 兩者差別在非簡單請求會在真的發出 request 前先發一個預檢請求 `preflight request` ,在有 CORS 的情況下又有滿足以下條件時候會發生 * Request Method 非`GET` `POST` `HEAD` ( HEAD 跟 GET 很像差在沒有 response body) * Content-Type 非 `text/plain` `multipart/form-data` `application/x-www-form-urlencoded` * 有自訂 header (這我不太清楚是怎) 這個 preflight 的 Method 會是 `OPTIONS`,解決方式也是在後端加上 `Access-Control-Allow-Headers` 來允許某自定義的 header 簡單說,preflight 是個驗證機制,確保後端知道前端要送的 request 是預期的,瀏覽器才會放行。 ### 帶上 cookie 如果要帶上 cookie 的話,那 `Access-Control-Allow-Origin` 不能是 *,一定要明確指定 origin。 需要在發送 request 的時候帶上 cookie,必須滿足三個條件: 1. 後端 Response header 有 `Access-Control-Allow-Credentials: true` 2. 後端 Response header 的 `Access-Control-Allow-Origin` 不能是 *,要明確指定 3. 前端 fetch 加上 `credentials: 'include'` ### 面試問答環節 Q : 為什麼要(會)有 CORS ? A : 瀏覽器有同源政策,瀏覽器會擋你的跨來源請求,是因為安全性問題。 Q : 怎麼解決 CORS 問題 ? A : 見 [簡單請求與非簡單請求](#簡單請求與非簡單請求),算起來根本沒什麼前端的事情,就是發現 CORS 然後回報後端,但有個概念後才知道如何解決,大概就是在 req 跟 res 的 header 上做手腳這樣 Q : CORS 是擋 request 嗎 ? A : 簡單請求的話不是,擋的是 response ; 非簡單請求的話是,這邊會先送一個 `preflight`,如果驗證沒過,則 request 不被送出