[CORS] 1. CORS 是什麼? 為什麼要有 CORS ?
什麼是 CORS?
先來說明一下什麼是 Origin
:
Origin
: 由 protocol
+ host
+ port
,ex:
- https://www.benson-chen.com
- http://www.mecha-chen.com:80
- https://www.hello-world.com:443
如果 fetch, XMLHTTPRequest 的 api origin 不一樣,就會被 Cross Origin Resource Sharing (CORS)
policy 阻擋
script
, img
的 src 不在此限制因為像 script
, img
的 src 只是取得資源,對 Server 沒有什麼安全上的疑慮,所以沒有在 CORS policy 的限制範圍裡
為什麼要有 CORS?
簡單來說,就是
你是從其他家 domain 來的,要跟我家 domain 的 Server 互動是有些規範的
沒有 CORS 的話,駭客就可以在任意網站去跟你的 Server 做互動了
陷阱: Server 其實還是會處理 request
雖說有了 CORS 之後,駭客不能隨意跟 Server 互動,但是阻擋的方式只是
Browser 不把 "已經取得 respones 的結果" 回傳給你看
驚不驚喜,意不意外 😈😈😈
怎麼說呢? 你會看見的錯誤訊息如下:
request has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource
有沒有發現亮點? Access-Control-Allow-Origin
是 Server 的 response 才會加上的 header,表示 Server 其實已經處理完 request 了
那如果我們的 request 其實會去更改 DB 的資料,像是 PUT /user/:id
或是 DELETE /user/:id
呢?
那這時候就悲劇了,就算有 CORS 的保護,Server 的 DB 資料還是會被砍掉,所以呢? 又有另外一個機制幫我們去區分 request,來針對不同安全程度的 request 做不同的處理,分別是 簡單請求 & 一般請求,我們接下來就會針對這 2 種請求來做說明
簡單請求
在只符合特定簡單內容的條件下,因為安全性疑慮比較低,會直接對 Server 發送請求
請求內容
- Method:
GET
,POST
,HEAD
- Request header:
Accept
Accept Language
Content-Language
Content-Type
:application/x-www-form-urlencoded
,multipart/form-data
,text/plain
一般請求
如果不符合上述簡單請求的條件,會對 Server 先發送 Preflight request ,再發送一般 request
Preflight Request (預檢請求)
會先對 Server 發送預檢請求,表示有哪一些 HTTP method 的 options,故發送的 request 為 HTTP OPTION
method,範例如下
OPTIONS /data/
Host: othersite.com
Origin: https://shubo.io
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-MY-CUSTOM-HEADER, Content-Type
HTTP 方法的命名通常與其功能和目的有關。對於 "OPTIONS" 這個名稱,其背後的原因可以從兩個方面來理解:
- 提供選項(Options):OPTIONS 方法的主要目的是提供關於目標資源可用的通信選項。換句話說,它告訴客戶端可以對特定資源進行哪些操作,這些操作就是客戶端的“選項”。所以,從這個角度來看,“OPTIONS”這個名稱反映了這個方法的核心功能,即提供有關資源的可用方法和限制的信息
example: js POST fetch
fetch('https://othersite.com/data/', {
method: 'POST',
headers: {
'Content-Type': 'application/json', // 非簡單請求
'X-CUSTOM-HEADER': '123'
}
})
Preflight request
傳送
OPTIONS
method: 跟 Server 說我想要確認哪些 method 在此 domain 下可以用Host
: Client 的 hostOrigin
: Client 的 domainAccess-Control-Request-Method
: Client 要允許的 methodAccess-Control-Request-Headers
: Client 要允許的 headers
```plaintext
OPTIONS /data/
Host: othersite.com
Origin: https://shubo.io
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-MY-CUSTOM-HEADER, Content-Type
Preflight response
Access-Control-Allow-Methods
: Server 允許的 HTTP 方法。Access-Control-Allow-Headers
: Server 允許的非「簡單」header。
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: X-MY-CUSTOM-HEADER, Content-Type
一般 Request & Response
request:
POST /data/
Host: othersite.com
Origin: https://shubo.io
Content-Type: application/json
X-MY-CUSTOM-HEADER: 123
response:
Access-Control-Allow-Origin: https://shubo.io
結論
- 有了 CORS,就可以阻擋 CSRF,避免 hacker 使用 client cookie 取得 client 相關資訊或更改 client 相關資訊
- 即便有了 CORS,還是會跟 Server 請求成功,只是簡單請求的話,response 會被 browser 阻擋,一般 request 的話,如果 preflight response fail 了,才會阻擋接下來的請求
參考資源
- [教學] 深入了解 CORS (跨來源資源共用): 如何正確設定 CORS? - Shubo 的程式開發筆記
- CORS 是什麼? 為什麼要有 CORS? |ExplainThis
- 面试官问我CORS跨域,我直接一套操作斩杀! - 掘金 (juejin.cn)
- 零基礎資安系列(一)-認識 CSRF(Cross Site Request Forgery) (cymetrics.io)
- 你是怎样解决跨域问题的?-面试必问-腾讯云开发者社区-腾讯云 (tencent.com)
- 前端面试查漏补缺–(三) 跨域及常见解决办法 - 射手猫的个人博客 (shotcat.com)
- CORS in 100 Seconds - YouTube