CORS 介绍
CORS(Cross-Origin Resource Sharing)是一种跨域访问技术,用于解决跨域请求的问题。在发送跨域请求前,用户浏览器会先发送一个预检请求。预检请求使用 OPTIONS 方法,包含 Origin 请求头用于指示请求的来源。
服务器收到预检请求后,根据服务器上的跨域配置:
- 如果 Origin 的值不在服务器上的
Access-Control-Allow-Origin
列表中,服务器响应 403 状态码,表示不允许来自该 Origin 的请求。 - 如果 Origin 的值在
Access-Control-Allow-Origin
列表中,服务器在预检请求的响应中至少会包含Access-Control-Allow-Origin
与Access-Control-Allow-Methods
头部。Access-Control-Allow-Origin
告知浏览器哪些请求来源是合法的。Access-Control-Allow-Methods
告知浏览器在发送跨域请求时可以使用的方法。之后,浏览器发送跨域请求。
备注:本文不对 CORS 原理做详细描述。上述介绍仅服务于本文主题。
CDN + TOS 的跨域场景
在火山引擎内容分发网络(CDN)中,您可以设置源站为火山引擎对象存储(TOS)中的一个存储桶,对存储桶中的文件进行传输加速。在 CDN 缓存来自存储桶的文件时,该文件的响应头会随文件一起被缓存。
在 CDN + TOS 的场景中,跨域配置有以下几种方式。但是每种方式下都可能会出现跨域问题。
方式一:仅在存储桶设置跨域配置
在该方式下,如果您修改了存储桶的某个跨域配置,该配置可能无法生效,原因如下:
- 配置修改后,CDN 中已缓存文件的源站响应头不会更新。对于这些文件的请求,CDN 响应中包含的依然是更新前的跨域配置。
方式二:仅在 CDN 中设置跨域配置
在该方式下,如果存在预检请求,用户的跨域请求可能会失败,原因如下:
- 因为 CDN 不会缓存预检请求的结果,CDN 会将收到的预检请求转发到 TOS。由于存储桶没有跨域配置,导致 TOS 响应 403 状态码。接着,CDN 将该 403 状态码返回给用户。
方式三:在存储桶和 CDN 中设置相同的跨域配置
在该方式下,如果您修改了存储桶或者 CDN 中的某个跨域配置,但是没有在两边及时同步,那么跨域请求的结果可能会不符合预期。
CDN + TOS 的推荐跨域配置
要避免这些跨域问题,我们推荐您两种配置。
推荐配置一
该配置实施方便,但存在配置冗余。在该配置下,您需要完成以下步骤:
- 在存储桶和 CDN 中都设置相同的跨域配置。
- 任何的跨域配置更新都及时在存储桶和 CDN 同步。
推荐配置二
该配置有点复杂,但没有冗余,可以帮助您理解配置原理。在该配置下,您需要完成以下步骤:
- 在存储桶中,仅设置 来源 Origin 与 操作 Methods。
- 在 CDN 中,设置所有的跨域配置。
- 如果
Access-Control-Allow-Origin
或Access-Control-Allow-Methods
的配置需要更新,您需要确保 CDN 和存储桶中的配置保持同步。 - 其余跨域配置仅需在 CDN 中维护更新。
备注:
- 在存储桶中设置 来源 Origin 与 操作 Methods 的目的是为了 TOS 能正确响应预检请求。
- 在 CDN 的响应中,CDN 中的跨域配置会覆盖存储桶中的跨域配置。
Access-Control-Allow-Origin
列表包含多个域名或者泛域名时的额外配置
如果您配置的 Access-Control-Allow-Origin
列表包含多个域名或者泛域名,您需要额外完成以下步骤。
- 在 CDN 中设置 HTTP 响应头
Vary: Origin
。该配置的说明如下:- 如果该配置未开启,假设一个跨域请求的文件已在本地缓存中,但是该缓存文件的 Origin 与该跨域请求的 Origin 不同,那么结果可能会不符合预期。因为在这个情况下,即使该跨域请求的 Origin 在您配置的
Access-Control-Allow-Origin
列表中,也会因为与缓存文件的 Origin 不匹配而导致跨域请求失败。
- 该配置开启后,不同 Origin 但是 URL 相同的跨域请求会被客户端认为是不同的请求而发送给 CDN。同时,客户端也会在本地缓存中为每个 Origin 的请求创建各自的文件副本。这样,跨域请求的结果可以符合预期。
- 如果该配置未开启,假设一个跨域请求的文件已在本地缓存中,但是该缓存文件的 Origin 与该跨域请求的 Origin 不同,那么结果可能会不符合预期。因为在这个情况下,即使该跨域请求的 Origin 在您配置的
- 在 CDN 中设置 跨域校验 为 开启。关于该配置的说明,参见 配置 HTTP 响应头。
备注:
- 不建议您在存储桶设置 返回 Vary:Origin 为 开启。虽然不会造成请求结果不符合预期,但是对于一个用户请求(包括跨域请求和非跨域请求),只要请求的文件不在本地缓存,该请求就会触发 CDN 向源站请求该文件或者做回源校验。这会导致回源请求数增加。
- 如果您配置
Access-Control-Allow-Origin
为*
,则无需设置 HTTP 响应头Vary: Origin
。同时,跨域校验 可以保持为 关闭。
操作示例
假设您希望在 CDN + TOS 场景下设置以下跨域配置:
- Access-Control-Allow-Origin:https://*.example.com,https://www.test.com
- Access-Control-Allow-Methods:GET,POST
- 预检请求结果的有效期:1小时
如果您使用推荐配置二,在存储桶和 CDN 中的配置如下。
存储桶配置
在存储桶中,设置以下跨域配置:
CDN 配置
在 CDN 的 “HTTP 响应头” 配置中,设置以下头部。
更多信息
如果您的源站是其他云厂商的对象存储桶,或者您的源站本身就有跨域配置,也可以参考本文档的思路进行相应设置。