配置跨域资源共享 (CORS)

更新时间:

当网站加载 OSS 资源时,浏览器报"blocked by CORS policy"错误,是因为浏览器的同源策略:只允许网页访问相同协议、域名和端口的资源。比如网站 https://www.example.com 无法直接访问不同域名的 OSS 资源 https://example-bucket.oss-cn-hangzhou.aliyuncs.com/test.jpg image 通过为 OSS 配置跨域资源共享(CORS)规则,可以安全授权指定网站访问 OSS 资源,让网页直接操作文件。

工作原理

CORS 请求分为两种类型:简单请求和预检请求。简单请求可以直接发送,预检请求必须先获得许可才能发送主请求。

如果满足以下任何一种情况,系统将对请求执行预检:

  • 请求使用的是 GET HEAD POST 以外的方法。

  • 请求使用 POST 方法且 Content-Type 不是 text/plain application/x-www-form-urlencoded multipart/form-data

  • 请求设置了自定义头部,例如 x-oss-*

当浏览器向 OSS 发出简单请求时,会发生以下过程:

  1. 浏览器将 Origin 头部添加到请求中。 Origin 头部包含相应资源的来源,例如 Origin: https://www.example.com

  2. OSS 将请求的 HTTP 方法以及 Origin 头部的值与目标 Bucket CORS 配置进行比较,查找匹配项。如果存在匹配项,OSS 将在响应中包含 Access-Control-Allow-Origin 头部。 Access-Control-Allow-Origin 头部包含初始请求的 Origin 头部的值。

  3. 浏览器接收响应并检查 Access-Control-Allow-Origin 值是否与原始请求的域名匹配。如果匹配,则请求成功。如果不匹配,或者响应中不存在 Access-Control-Allow-Origin 头部,则请求失败。

预检请求首先执行以下步骤,成功后再执行与简单请求相同的过程:

  1. 浏览器发送一个 OPTIONS 请求,包含主请求的方法( Access-Control-Request-Method )和头部( Access-Control-Request-Headers )信息

  2. OSS 根据 CORS 配置检查请求的方法和头部是否被允许。如果预检请求中的任何方法或标头值未包含在目标资源允许的方法和标头集合中,请求将失败,并且不会发送主请求。

网站静态资源加载

网站 https://www.example.com 需要加载存放在 OSS 上的图片、CSS JS 文件。

步骤一:配置 CORS 规则

登录 OSS 管理控制台 ,进入目标 Bucket 数据安全 > 跨域设置 ,创建规则如下:

参数

配置值

说明

来源

https://www.example.com

只允许来自该特定网站的请求,保障资源安全。

允许 Methods

GET , HEAD

GET 下载资源,HEAD 用于缓存校验。

允许 Headers

留空

此场景为简单请求,不触发预检,因此该项配置不会被用到,留空即可。

暴露 Headers

ETag , Content-Length

  • ETag : 允许浏览器通过 HEAD 请求进行缓存校验,若文件未变则返回 304 Not Modified ,避免重复下载。

  • Content-Length : 可用于在前端显示资源加载进度。

缓存时间

86400

缓存预检结果 24 小时,减少未来可能产生的预检请求。

返回 Vary Origin

不勾选

由于来源是单一且确定的,无需开启此项来处理多域名缓存问题。

步骤二:验证配置

访问 https://www.example.com ,确认 OSS 资源(如图片)加载正常,且浏览器控制台无 CORS 错误。

前端直传文件

用户在网页 https://app.example.com 上,将头像、文档等文件直接上传到 OSS。

步骤一:配置 CORS 规则

登录 OSS 管理控制台 ,进入目标 Bucket 数据安全 > 跨域设置 ,创建规则如下:

参数

配置值

说明

来源

https://app.example.com

确保只有该授权应用有权限执行上传操作。

允许 Methods

PUT , POST

PUT POST 是执行上传操作必需的 HTTP 方法。

允许 Headers

*

前端直传的安全性不依赖固定的 Authorization 头,而是由有时效性的临时签名 (STS 或预签名 URL)保障。使用 * 可兼容 SDK 携带的多种头部(如 x-oss-meta-* ),简化配置且无安全风险。

暴露 Headers

ETag , x-oss-request-id

  • ETag:是文件上传成功的唯一标识,用于后续校验。

  • x-oss-request-id :若上传失败,前端可捕获此 ID,在寻求技术支持时提供,以便快速定位问题。

缓存时间

600

上传操作频率相对较低,缓存 10 分钟既能减少预检,又能快速响应配置变更。

返回 Vary Origin

勾选

为未来可能的多域名部署(如测试环境)做准备,避免 CDN 缓存污染。

步骤二:验证配置

https://app.example.com 页面执行上传操作,确认文件成功上传至 OSS,且浏览器控制台无 CORS 错误。

多环境支持

开发、测试、生产等多个子域名(如 dev.example.com , app.example.com )需要访问同一个 OSS 资源。

步骤一:配置 CORS 规则

登录 OSS 管理控制台 ,进入目标 Bucket 数据安全 > 跨域设置 ,创建规则如下:

参数

配置值

说明

来源

https://*.example.com

使用 * 通配符一次性授权 example.com 下所有 https 协议的子域名。

允许 Methods

GET , PUT , POST

同时允许资源的读取和上传,满足多环境下的测试需求。

允许 Headers

*

多环境开发中,不同环境、不同功能可能引入不同的自定义头部。使用 * 可以避免频繁修改 CORS 规则。

暴露 Headers

ETag , x-oss-request-id

同时支持下载校验和上传结果反馈。

缓存时间

3600

1 小时的缓存时间,在多环境切换和调试时较为灵活。

返回 Vary Origin

勾选

必须开启。告知 CDN 根据 Origin 头区分缓存,防止多环境间缓存错乱。

步骤二:验证配置

分别在 https://dev.example.com https://app.example.com 上进行访问或上传测试,确认操作均成功。

带认证信息的 API 式调用

前端应用 https://api.example.com 需要携带 Authorization 等自定义头部访问受保护的 OSS 资源。

步骤一:配置 CORS 规则

登录 OSS 管理控制台 ,进入目标 Bucket 数据安全 > 跨域设置 ,创建规则如下:

参数

配置值

说明

来源

https://api.example.com

对于携带认证信息的请求,来源必须是精确的、受信任的域名。

允许 Methods

GET , PUT , DELETE

支持对私有资源的读取、更新和删除全生命周期管理。

允许 Headers

authorization , content-type , x-oss-*

严禁使用 * 。明确列出所有必要的请求头,遵循最小权限原则,避免泄露不必要的头部信息。

暴露 Headers

ETag , x-oss-request-id

提供操作成功后的校验标识和失败后的排错 ID

缓存时间

600

对于认证类请求,较短的预检缓存时间(10 分钟)有助于更快地应用安全策略变更。

返回 Vary Origin

勾选

告知 CDN 为不同 Origin 的请求分别缓存,避免混淆。

步骤二:验证配置

https://api.example.com 页面发起带 Authorization 头的请求,确认能成功访问受保护的 OSS 资源。

应用于生产环境

安全最佳实践

遵循最小权限原则。

  • 精确配置 来源(AllowedOrigin) :除非 Bucket 是完全公开的,否则严禁将 AllowedOrigin 设置为 * 。应精确指定提供服务的网站域名,例如 https://www.example.com

  • 收紧 允许 Methods(AllowedMethod) :只开放业务必需的 HTTP 方法。如果网站只需要读取数据,则只配置 GET HEAD

  • 具体指定 允许 Headers(AllowedHeader) :对于携带认证信息(如 Authorization 头)的请求,严禁使用 * ,必须明确列出所有必要的请求头。

性能最佳实践

  • 优化预检缓存:为 缓存时间 (MaxAgeSeconds) 设置一个合理的值(如 86400 秒,即 24 小时),可以显著减少预检请求的数量,降低延迟和请求成本。

  • 评估 Vary: Origin 的影响:启用 返回 Vary: Origin 虽然可以解决缓存污染问题,但会增加 CDN 缓存的复杂性,可能导致缓存命中率下降和回源流量增加,从而产生额外成本和延迟。请在评估后使用。

CDN 加速场景

如果 Bucket 开启了 CDN 加速并使用 CDN 域名访问,跨域请求将首先到达 CDN 节点。此时,必须在 CDN 控制台配置 CORS 规则,而不是在 OSS。OSS 侧的 CORS 配置仅在请求直接访问 OSS 源站域名时生效。详情请参见 配置跨域资源共享

CORS 规则参数说明

每个 Bucket 最多可以配置 20 条跨域规则。OSS 按照配置的规则顺序,从上到下依次检查,并使用第一条成功匹配的规则。一旦匹配成功,后续规则将不再检查。

参数

是否必须

说明

来源 (AllowedOrigin)

指定哪些网站(来源域)可以跨域访问 OSS 资源。

  • 格式为 协议://域名[:端口] ,例如 https://www.example.com

  • 支持 * 通配符,但每个来源中最多只能使用一个。

    • 有效示例 https://*.example.com http://localhost:*

    • 无效示例 https://*.example.* https://*

  • 允许多个来源,每行一个。

允许 Methods (AllowedMethod)

指定允许的 HTTP 方法。

  • 可选值: GET , PUT , POST , DELETE , HEAD

  • 允许多个方法。

允许 Headers (AllowedHeader)

作用于预检请求,决定了实际请求中允许携带的 HTTP 头部。

  • 支持 * 通配符,表示允许所有头部。

  • 允许多个 Header,每行一个,大小写不敏感。

暴露 Headers (ExposeHeader)

允许前端 JavaScript 代码可以访问到 OSS 响应中的哪些头部信息。

  • 不支持 * 通配符。

  • 允许多个 Header,每行一个。

  • 使用场景: 如需在 JS 中获取上传文件的 ETag x-oss-request-id ,必须在此处添加 ETag x-oss-request-id

缓存时间 (MaxAgeSeconds)

指定浏览器缓存 OPTIONS 预检请求结果的时间(单位:秒)。

  • 作用: 在缓存有效期内,对同一资源的相同跨域请求将不再发送预检请求,以优化性能。

返回 Vary: Origin

决定是否在响应中添加 Vary: Origin 头。此头告知 CDN 等中间缓存,需根据请求的 Origin 头来区分缓存版本,以避免多来源访问时的缓存污染问题。

  • 使用场景: 当来源配置了多个域名或通配符时,必须开启此项以避免缓存污染。

重要

开启此项可能导致 CDN 缓存命中率下降。

常见问题

报错 No 'Access-Control-Allow-Origin' header is present on the requested resource.

通常是由于浏览器缓存了不带 CORS 头的旧响应,或者 CORS 规则配置不当导致请求无法匹配任何规则。

建议先清除浏览器缓存进行测试。如果仍然报错,请参见以下步骤排查 CORS 跨域规则是否设置正确:

  1. 登录 OSS 管理控制台

  2. 单击 Bucket 列表 ,然后单击目标 Bucket 名称。

  3. 在左侧导航栏,选择 数据安全 > 跨域设置

  4. 在跨域设置页面,单击 创建规则

  5. 创建跨域规则 面板,将 来源 设置为 * 允许 Methods 全部勾选, 允许 Headers 设置为 * 暴露 Headers 设置为 ETag x-oss-request-id 缓存时间(秒) 设置为 0 ,选中 返回 Vary: Origin ,然后单击 确定

  6. 若问题仍然未解决,请任意登录一台服务器,执行以下命令,查看跨域请求头。

    curl -v -o output_file.txt -H 'Origin:[$URL2]' '[$URL1]'
    说明
    • [$URL1]为需要请求的 OSS 资源链接。

    • [$URL2]为您配置跨域规则的来源地址。

    系统显示类似如下。

    • 如果出现返回结果存在一个跨域头且符合您配置的跨域头,可能是由于您第一次请求没有触发跨域,返回的数据被本地缓存;而第二次触发跨域的请求没有请求服务器端,而是直接获取本地的缓存,导致跨域校验失败。 请参考以下解决方法:

      • 在浏览器页面单击 Ctrl + F5 ,清理浏览器缓存,然后在测试跨域问题是否还存在。

      • 您将该 OSS 资源跨域配置的 缓存时间 设置为 0,避免该资源在客户端进行缓存,每次请求都会重新在服务器端获取鉴权信息。

        说明

        您可以在上传文件时设置文件的 cache-control no-cache,已经上传的文件可以使用 ossutil 工具进行更改,如何设置 cache-control 请参见 set-meta(管理文件元数据)

      • 使用 CDN 加速 OSS,这样 CDN 所有请求都会返回 CORS 头。

    • 如果返回结果存在两个跨域头或者不符合您在 OSS 配置的跨域头,可能是由于使用了 CDN 加速 OSS:

      1. 登录 CDN 控制台 ,临时取消 CDN 加速 OSS,确认跨域问题不存在。

      2. 确认后,单击具体的域名,依次单击 缓存配置 > 节点 HTTP 响应头

      3. 根据您的实际情况,设定自定义 HTTP 响应头。

  7. 若跨域问题还是没有解决,请参见 OSS 跨域资源共享(CORS)出现的常见错误及解决方案 进一步排查处理。

报错 The 'Access-Control-Allow-Origin' header has a value '...' that is not equal to the supplied origin.

服务器返回了 Access-Control-Allow-Origin 头,但其值与当前请求的 Origin 不匹配。这通常是由于缓存问题导致的。当你配置了多个网站域名访问 OSS 时,浏览器或 CDN 可能记住了给其他网站的访问许可,然后错误地提供给当前网站使用。

请在 CORS 规则中开启 返回 Vary: Origin 选项,这样可以避免不同网站间的缓存混乱;或者清除浏览器缓存后重新访问。

报错 Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.

由于前端代码发送了携带凭证的请求, Access-Control-Allow-Credentials True ,但 Access-Control-Allow-Origin 的值被配置为通配符 * ,出于安全考虑,不允许使用通配符来源,以防止任意域访问资源并获取 Credentials 信息(包括 Cookies、Authorization Headers 等敏感数据)。

  • 如果您需要在请求头中保留 Credentials 信息,将 Access-Control-Allow-Origin 的值从通配符 * 修改为具体的域名(例如: https://example.com )。

  • 如果您不需要在请求头中保留 Credentials 信息,您可以在前端代码中将 xhr.withCredentials 设置为 false ,并确保服务器端的 Access-Control-Allow-Credentials 设置为 false

OSS 跨域加载慢如何提升加载速度?

跨域请求实际上是请求 Header 中携带 Origin 头请求 OSS Bucket 中的资源,所以加载快慢不取决于跨域,而是客户端到 OSS Bucket 的物理链路。如果客户端在中国香港,Bucket 是中国内地的,那访问是存在远距离访问的情况,推荐您使用 OSS 传输加速地址来访问,这样会对链路有加速优化,详情请参见 传输加速

说明

传输加速功能可以让全球各地的客户使用优化后的网络来传输数据,极大地提升上传和下载速度,让不同地域的用户都能有很好的访问体验。