前言
最近在碰一些資安的東東,發現自己對於這一塊知識都比較薄弱,身為前端工程師資安通常並不是首要關注的職責,但一但有漏洞保證後果不堪設想,於是近期來補足一下這方面的知識。
什麼是 CORS
CORS (Cross-Origin Resource Sharing) 跨來源資源共享,是一個機制用來決定網頁是否能夠存取其他來源的資源。
在提到 CORS 之前會先需要了解瀏覽器的同源政策(Same-Origin Policy),同源政策是瀏覽器的一個安全機制,限制了不同來源的網頁之間的互動,網頁來源可以被定義為三個部分:
- 協議(Protocol):
http
、https
- 主機(Host):
www.example.com
- 端口(Port):
80
、443
只有當這三個部分都相同時,瀏覽器才會認為是同源,否則就是跨來源。CORS 就是瀏覽器提供的防護網用來決定是否允許跨來源的請求。而這一項設定通常會需要在伺服端調整 CORS 相關設定。
CORS 設定
CORS 設定會在伺服器端進行,透過設定 HTTP 標頭來告訴瀏覽器是否允許跨來源請求。具體來說瀏覽器會將請求分為兩種:
簡單請求
- 只能是
GET
、POST
或HEAD
方法 - 自訂的 header 只能是
Accept
、Accept-Language
、Content-Language
或Content-Type
(值只能是application/x-www-form-urlencoded
、multipart/form-data
或text/plain
)根據 Fetch Spec - 發出請求的物件沒有註冊事件監聽器
- 請求中沒有
ReadableStream
的物件被用於上傳
簡單請求下 header 會帶上 Origin
來告訴伺服器請求的來源
伺服器會根據這個來源來決定是否允許跨來源請求,如果允許的話伺服器會在回應中加上 Access-Control-Allow-Origin
來告訴瀏覽器這個來源是被允許的。
非簡單請求
前面有特別提到這是一項瀏覽器的機制用來阻擋非同源的請求,特別有些請求是只要送出就可能改變伺服器狀態像是:POST
、PUT
、DELETE
(或是任何非簡單請求),沒辦法單純的獲取請求後再決定要不要阻擋,因此這類請求會透過預檢請求(Preflight Request)也就是預先送出一個 OPTIONS
請求詢問伺服器是否允許操作:
然後伺服器回應允許該請求:
確定該非簡單請求是可以被接受的後,瀏覽器才會真正發送請求:
並且伺服器回應允許的來源:
總結
CORS 是現代網頁應用中不可或缺的安全機制,能有效防止不同來源之間的不正當資源存取。透過 CORS,可以在保護用戶資料的同時,允許合法的跨來源請求。
延伸閱讀
- Same-origin policy - mdn
- CORS in 100 Seconds - Fireship
- I Hate CORS. - Theo - t3.gg
- 跨來源資源共用(Cross-Origin Resource Sharing, CORS)簡介 - 李嘉峻