CORS
通過控制 Access-Control-Allow-Origin
控制哪些域名可以共享資源,取值如下
Access-Control-Allow-Origin: <origin> | *
其中 *
代表所有域名,origin
代表指定特定域名,那如何設置多個域名了?
此時需要通過代碼實現,根據請求頭中的 Origin
來設置響應頭 Access-Control-Allow-Origin
,那 Origin 又是什么東西?
請求頭: Origin
並不是所有請求都會自動帶上 Origin
,在瀏覽器中帶 Origin
的邏輯如下
- 如果存在跨域,則帶上
Origin
,值為當前域名 - 如果不存在跨域,則不帶
Origin
邏輯理清楚后,關於服務器中對於 Access-Control-Allow-Origin
設置多域名的邏輯也很清晰了
- 如果請求頭不帶有
Origin
,證明未跨域,則不作任何處理 - 如果請求頭帶有
Origin
,證明跨域,根據Origin
設置相應的Access-Control-Allow-Origin: <Origin>
使用偽代碼實現如下:
// 獲取 Origin 請求頭 const requestOrigin = ctx.get('Origin'); // 如果沒有,則跳過 if (!requestOrigin) { return await next(); } // 設置響應頭 ctx.set('Access-Control-Allow-Origin', requestOrigin)
Vary: Origin
此時可以給多個域名控制 CORS,但此時假設有兩個域名訪問 static.shanyue.tech
的跨域資源
foo.shanyue.tech
,響應頭中返回Access-Control-Allow-Origin: foo.shanyue.tech
bar.shanyue.tech
,響應頭中返回Access-Control-Allow-Origin: bar.shanyue.tech
看起來一切正常,但如果中間有緩存怎么辦?
foo.shanyue.tech
,響應頭中返回Access-Control-Allow-Origin: foo.shanyue.tech
,被 CDN 緩存bar.shanyue.tech
,因由緩存,響應頭中返回Access-Control-Allow-Origin: foo.shanyue.tech
,跨域出現問題
此時,Vary: Origin
就上場了,代表為不同的 Origin
緩存不同的資源
總結 (簡要答案)
CORS 如何指定多個域名?
根據請求頭中的 Origin
來設置響應頭 Access-Control-Allow-Origin
,思路如下
- 總是設置
Vary: Origin
,避免 CDN 緩存破壞 CORS 配置 - 如果請求頭不帶有
Origin
,證明未跨域,則不作任何處理 - 如果請求頭帶有
Origin
,證明瀏覽器訪問跨域,根據Origin
設置相應的Access-Control-Allow-Origin: <Origin>
使用偽代碼實現如下
// 獲取 Origin 請求頭 const requestOrigin = ctx.get('Origin'); ctx.set('Vary', 'Origin') // 如果沒有,則跳過 if (!requestOrigin) { return await next(); } // 設置響應頭 ctx.set('Access-Control-Allow-Origin', requestOrigin)