跨來源資源共用(CORS)
故事背景
今日上班的時候,隔壁的小王跑來跟我說,目前線上遇到CORS的問題,深入了解後才曉得在後端的工程人員對於CORS的認識不深,因此在進行新環境部署的時候缺少環境的設定檔,面對總是有類似的狀況一再發生,是否有什麼方式可以改善。
同源策略
要說起CORS的由來,主要還是在於安全性考量,在瀏覽器上大部份是採用同源政策(Same-origin policy)限制了不同網域資源間的活動。因此當我們API站的網址、埠號、協定不一致的時候,通常我們會在開發者工看到下面的錯誤訊息:

CORS
隨著目前網站提供的功能與內容的豐富度越來越高,經常會有需要存取第三方資源的狀況,因此大部份都會透過一些跨域存取的方法達到請求資源的目的,CORS就是其中一種可以達成存取資源方法。伺服器會透過preflight request
機制使用OPTIONS
方法發出一個請求,確認伺服器是否支援跨域請求以及相關內容,當伺服務允許之後,才會實際發送資源請求的動作,並告知客戶端是否有需要相關的認證資訊(Cookie、Header)之類的。
解法方法
根據伺服器的不同,通常很容易在網路上找到各自對應的設定方式,這邊我以大家常使用的nginx
伺服器設定進行解說,如果想要更進一步的了解,可以參考阮一峰大大的這篇日誌。
在nginx
的設定檔加入下述參述
1 | location / { |
Access-Control-Allow-Origin
當設定為 *
即表示伺服器接受跨域請求。
Access-Control-Allow-Methods
這邊需指定伺服器允許的請求方式有哪些,一般常見的的會是 OPTIONS
、GET
、POST
,可以根據需要進行設定。
Access-Control-Allow-Headers
這邊需指定伺服器可接受的檔頭內容,可以根據需要進行設定。
withCredentials
CORS請求在預設上不會涉及Cookie相關認證的處理,如果需要客端將Cookie發送至伺服器除
在xhr
上需要設定withCredentials
參數
1 | var xhr = new XMLHttpRequest(); |
伺服器也需要指定檔頭的設定
1 | add_header 'Access-Control-Allow-Credentials' 'true'; |
測試CORS設定是否生效
要曉得伺服務是否支援CORS,經由正式的客端環境透過瀏覽器發求資源請求是比較正規的方式,但是理解原理後,也可以透過寫一些腳本來輔助我們進行新環境的檢查,下面舉一個簡單請求
測試範例供參考。
使用curl
指令測試氣象資料開放平臺的API請求
1 | curl -I -X OPTIONS \ |
從 Response Header 看到Access-Control-Allow-Origin
欄位設定是否正確
1 | HTTP/1.1 200 OK |
如果非簡單請求的狀況,可以進一步檢視回應中Access-Control-Allow-Methods
、Access-Control-Allow-Headers
、Access-Control-Allow-Credentials
這些字段是否與伺服器上的設定是相符的。