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.techbar.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)
