OBS提供HTML5协议中的CORS设置,帮助用户实现跨域访问。
您可以新建CORS规则,也可以从其他桶复制已有CORS规则。
使用场景
在通常的网页请求中,浏览器的同源安全策略(Same Origin Policy,SOP)只允许网页访问相同协议、域名和端口的资源,不同域(协议/域名/端口不同)之间的网站脚本和内容是无法进行交互的,即由于JavaScript同源策略的限制,A域名下的JavaScript无法操作B域名或C域名下的对象。OBS支持CORS规范,允许跨域请求访问OBS中的资源。
跨域资源共享(Cross Origin Resource Sharing,CORS)是由W3C标准化组织提出的一种网络浏览器的规范机制。它定义了一个域中加载的客户端Web应用程序与另一个域中的资源交互的方式。
OBS支持CORS规范,允许跨域请求访问OBS中的资源。
OBS支持静态网站托管,而只有当对该桶设置了合理的CORS配置,OBS中保存的静态网站才能允许响应另一个跨域网站的请求。
CORS的典型应用场景包括:
- 通过CORS支持,使用JavaScript和HTML5来构建Web应用,直接访问OBS中的资源,而不再需要代理服务器做中转。
- 使用HTML5中的拖拽功能,直接向OBS上传文件,展示上传进度,或是直接从Web应用中更新内容。
- 托管在不同域中的外部网页、样式表和HTML5应用,现在可以引用存储在OBS中的Web字体或图片,让这些资源能被多个网站共享。
CORS配置会在两分钟内生效。
OBS系统提供的默认配置为根域名跨域访问允许所有域访问,会使客户端存在被攻击的风险。
客户端可通过在自己的桶内创建配有自己规则的crossdomain.xml,并在其flash代码中添加Security.loadPolicyFile("https://bucket.obs.cn-north-4.myhuaweicloud.com/crossdomain.xml"),从而避免被攻击的风险。其中,bucket.obs.cn-north-4.myhuaweicloud.com需根据实际情况替换为自己桶的访问域名。
工作原理
两个页面同协议、同域名(或IP)、以及同端口视为同一个域(同源),两个页面的协议、域名、端口三者有一个不相同,即为跨域。为了更好地理解跨域原理,您可以查看表1。
表1 同源检测示例 | 当前页面 | 请求的资源 | 是否跨域 | 访问结果 | 原因 |
| https://support.huaweicloud.com/dir/test.html | https://support.huaweicloud.com/dir/other.html | 否 | 成功 | 同源(协议、域名、端口都相同) |
| https://support.huaweicloud.com/dir/test.html | https://support.huaweicloud.com/dir/inner/other.html | 否 | 成功 | 同源(协议、域名、端口都相同) |
| https://support.huaweicloud.com/dir/test.html | http://support.huaweicloud.com/dir/test.html | 是 | 失败 | 协议不同 |
| https://support.huaweicloud.com/dir/test.html | https://support.huaweicloud.com:81/dir/test.html | 是 | 失败 | 端口不同 |
| https://support.huaweicloud.com/dir/test.html | https://help.huaweicloud.com/dir/test.html | 是 | 失败 | 域名不同 |
当网页请求OBS资源时,由于网页和OBS的域名不同,浏览器会检查OBS是否明确允许该跨域访问:
- 当在OBS未配置相应的CORS规则时,浏览器将会拒绝访问并报错。
- 当在OBS配置CORS规则后,可以向浏览器明确哪些跨域请求是被允许的。当网页和OBS的CORS规则匹配成功后,OBS会在响应中返回Access-Control-Allow-Origin等请求头,浏览器收到后才允许网页访问OBS资源。
约束与限制
一个桶最多可设置100条CORS规则。
新建CORS规则
OBS支持通过管理控制台、API、SDK方式新建CORS规则,不支持通过OBS Browser+、obsutil方式新建CORS规则。
使用OBS控制台
- 在OBS管理控制台左侧导航栏选择“桶列表”。
- 在桶列表中,单击待操作的桶,进入“对象”页面。
- 在左侧导航栏,单击“数据安全 > CORS规则”。
- 单击“创建”,系统弹出“创建CORS规则”对话框,如图1所示。
图1 创建CORS规则 
- 在“创建CORS规则”弹窗中,配置相关参数。
表2 CORS规则参数说明 | 参数名称 | 是否必选参数 | 说明 |
| 允许的来源 | 是 | 指定允许的跨域请求的来源,即指定允许哪些网站可以访问该OBS桶。 格式为:协议://域名:端口,其中“端口”可选。 |
| 允许的方法 | 是 | 指定允许的跨域请求方法,即指定允许哪些请求对桶和对象执行操作。 支持选择多个方法。 允许的方法: - Get:允许来自对OBS桶和对象进行所有获取操作的请求,如:获取桶位置/桶策略、查看桶存量、获取对象内容、获取对象ACL。
- Post:允许来自对OBS桶和对象进行所有更新操作的请求,如:修改桶策略、桶ACL、对象ACL。
- Put:允许来自对OBS桶和对象进行所有设置操作的请求,如:设置桶策略、桶ACL、对象ACL。
- Delete:允许来自对OBS桶和对象进行所有删除操作的请求,如:删除桶策略、删除对象、删除桶。
- Head:允许来自对OBS桶和对象进行所有获取非具体内容的操作请求,如:获取桶元数据。
|
| 允许的头域(可选) | 否 | 指定实际请求中允许携带的请求头域,用于预检请求。关于预检请求相关介绍,请参见CORS请求的类型。 - 填写说明和约束:
- 允许的头域可设置多个,多个头域之间换行隔开,大小写不敏感。
- 每行最多可填写一个*符号。
- 如果允许的头域填写“*”,则表示允许跨域请求中携带任意头域。
- 不支持&、:、<、空格以及中文字符。
- 常用的头域:
- Authorization:请求消息中携带的签名信息。
- Content-Length:消息(不包含消息头)长度。
- Content-Type:资源内容的类型,如:text/plain。
- Date:请求发起端的日期和时间。
- Host:请求的主机和端口号。
- Cache-Control:指定缓存指令。
- Connection:控制网络连接,如:keep-alive。
- User-Agent:发送请求的用户代理信息,如:浏览器类型。
- Accept:客户端可处理的内容类型。
- Accept-Language:客户端可以接受的自然语言。
- Accept-Encoding:客户端可以接受的内容编码。
- Accept-Charset:客户端可以接受的字符集。
|
| 补充头域(可选) | 否 | 允许跨域响应中返回指定的补充头域,给客户端提供额外的信息。默认情况下浏览器只能访问Content-Length、Content-Type等头域,如果还需要访问其他头域,需要在补充头域中配置。 - 填写说明和约束:
- 补充头域可设置多个,多个头域之间换行隔开。
- 不支持*、&、:、<、空格以及中文字符。
- 常用的补充头域:
- ETag
- x-obs-request-id
- x-obs-api
- Cache-Control
- Content-Disposition
- Content-Encoding
- Expires
- x-obs-id-2
- x-reserved-indicator
- x-obs-version-id
- x-obs-copy-source-version-id
- x-obs-storage-class
- x-obs-delete-marker
- x-obs-expiration
- x-obs-website-redirect-location
- x-obs-restore
- x-obs-version
- x-obs-object-type
- x-obs-next-append-position
|
| 缓存时间(可选) | 是 | 指定请求来源的客户端(浏览器)可以缓存OPTIONS预检请求结果的时间。 在缓存有效期内,对同一资源的相同跨域请求将不再发送预检请求。 以秒(s)为单位,默认为100秒,取值范围:0~9999999。 |
- 单击“确定”。
在CORS规则列表页可以看到新创建的CORS规则即表示创建桶的CORS配置成功。CORS配置会在两分钟内生效。
例如:为桶“testbucket”允许的来源配置为“https://www.example.com”,允许的方法配置为“GET”,允许的头域配置为“*”,补充头域配置为“ETag”,缓存时间设置为“100”。该配置表示OBS仅允许来源为“https://www.example.com”的“GET”请求访问桶“testbucket”,且不限制该请求的头域,允许响应中返回ETag值,请求来源的客户端可缓存的该CORS请求的响应时间为100秒。
场景示例
以下介绍不同业务场景下的CORS规则配置。
网站加载OBS桶中的静态资源
网站https://www.testexample.com需要加载展示桶test-bucket中存储的图片、JS文件,在桶test-bucket中配置如下CORS规则:
表3 CORS规则参数配置 | 参数名称 | 配置值 | 说明 |
| 允许的来源 | https://www.testexample.com | 仅允许来自该网站的跨域请求访问桶test-bucket。 |
| 允许的方法 | 勾选“GET”和“HEAD”。 | GET和HEAD用于获取桶中的对象相关信息。 |
| 允许的头域(可选) | 置空 | 该场景为简单场景,不触发预检,因此无需配置。 |
| 补充头域(可选) | ETag
Content-Length | Etag用于验证对象完整性,Content-Length用于显示加载进度。 |
| 缓存时间(可选) | 86400 | 设置请求来源的客户端可以缓存预检请求结果的时间为24小时,减少预检请求。 |
上传文件至OBS桶
用户在网站https://www.testexample01.com上传个人简历、获奖证书、技术成果等文件到桶test-bucket01,在桶test-bucket01中配置如下CORS规则:
表4 CORS规则参数配置 | 参数名称 | 配置值 | 说明 |
| 允许的来源 | https://www.testexample01.com | 仅允许来自该网站的跨域请求访问桶test-bucket01。 |
| 允许的方法 | 勾选“PUT”和“POST”。 | PUT和POST用于上传或更新桶中的文件。 |
| 允许的头域(可选) | * | 使用浏览器上传对象的安全性由签名信息保障,此处使用“*”可以兼容SDK携带的多种头部。 |
| 补充头域(可选) | ETag
x-obs-request-id | - Etag:用于验证对象完整性。
- x-obs-request-id:是OBS创建来唯一确定本次请求的值,可以通过该值来定位问题。
|
| 缓存时间(可选) | 600 | 上传对象操作的频率相对较低,缓存10分钟既能减少发送预检请求,又能快速响应。 |
多个环境访问OBS桶
多条生产线(如:line01.testexample.com、line02.testexample.com)需要访问同一个桶test-bucket02中存储的文件,在桶test-bucket02中配置如下CORS规则:
表5 CORS规则参数配置 | 参数名称 | 配置值 | 说明 |
| 允许的来源 | https://*.testexample.com | 使用通配符“*”表示允许testexample.com域名下的所有HTTPS协议的子域名来跨域访问桶test-bucket。 |
| 允许的方法 | 勾选“GET”、“PUT”和“POST”。 | 允许上传和更新OBS桶中的文件。 |
| 允许的头域(可选) | * | 多条生产线协同工作访问桶,可能会引入不同的头域,因此使用“*”表示允许任意头域,避免频繁修改CORS规则。 |
| 补充头域(可选) | ETag
x-obs-request-id | - Etag:用于验证对象完整性。
- x-obs-request-id:是OBS创建来唯一确定本次请求的值,可以通过该值来定位问题。
|
| 缓存时间(可选) | 3600 | 设置请求来源的客户端可以缓存预检请求结果的时间为1小时,在多条生产线切换和调试时比较灵活。 |
使用携带签名信息的API访问OBS桶
网站https://api.testexample.com需要携带签名信息访问受保护的桶test-bucket03中存储的文件,在桶test-bucket03中配置如下CORS规则:
表6 CORS规则参数配置 | 参数名称 | 配置值 | 说明 |
| 允许的来源 | https://api.testexample.com | 仅允许来自该网站的跨域请求访问桶test-bucket03。 |
| 允许的方法 | 勾选“GET”、“PUT”和“DELETE”。 | 允许上传、更新和删除OBS桶中的文件。 |
| 允许的头域(可选) | Authorization
Content-Type | 对权限控制比较严格,严禁使用“*”,遵循最下权限原则。 跨域访问OBS桶的请求中携带签名信息和需要访问的资源类型。 |
| 补充头域(可选) | ETag
Content-Length | Etag用于缓存校验,Content-Length用于显示加载进度。 |
| 缓存时间(可选) | 600 | 设置请求来源的客户端可以缓存预检请求结果的时间为10分钟,有助于更快地进行安全策略变更。 |
CORS请求的类型
CORS机制中包含两种不同类型的请求:简单请求和预检请求,两者的区别在于是否需要先发送一个预检请求到服务器。
简单请求和预检请求需要的CORS规则配置也不同,如表7所示。
表7 简单请求和预检请求的CORS配置 | 请求类型 | 触发条件 | 需要的CORS配置 | 说明 |
| 简单请求 | 以下条件同时满足: - 请求方法:GET/POST/HEAD。
- 请求头仅限于以下几种:
- Accept
- Accept-Language
- Content-Language
- Content-Type:仅限application/x-www-form-urlencoded、multipart/form-data和text/plain。
- 没有自定义请求头。
| 允许的来源 | 简单请求只在服务端校验请求来源的域名,不校验请求方法和请求头。 |
| 预检请求 | 以下任意一条满足: - 请求方法:除GET/POST/HEAD之外的其他请求方法(如:PUT、DELETE等)。
- 请求头Content-Type的值为application/x-www-form-urlencoded、multipart/form-data和text/plain三个之外的其他值(如:application/json)。
- 带自定义请求头(如:x-obs-*)。
| 以下3个参数必须全部配置: | 预检请求需要在服务端校验请求来源的域名、请求方法、请求头。 当请求来源的域名、请求方法、请求头和在OBS侧配置的CORS规则匹配时,预检请求通过,客户端才会发送实际请求。 |
简单请求和预检请求的处理流程如下:
- 浏览器直接向OBS服务端发送实际请求,并自动携带Origin请求头(包含请求来源,如:Origin: https://www.example.com)。
- OBS服务端通过配置的CORS规则(配置的“允许的来源”)校验Origin请求头的值:
- 如果匹配,则OBS服务端会在响应中添加Access-Control-Allow-Origin响应头(值为“允许的来源”),并向浏览返回响应。
- 如果不匹配,则请求失败。
- 浏览器接收响应后,检查Access-Control-Allow-Origin响应头的值是否与原始请求的域名匹配:如果匹配,则请求成功,否则请求失败。
- 浏览器先发送一个不包含业务数据的OPTIONS预检请求到OBS服务端,该预检请求包含域名、请求方法和请求头。
- OBS服务端通过配置的CORS规则(配置的“允许的来源”、“允许的方法”、“允许的头域”、“缓存时间”)校验预检请求中携带的域名、请求方法、请求头:
- 如果全部匹配,OBS服务端会向浏览器返回预检通过的响应。
- 如果不全匹配,请求失败,且不会再发送实际请求。
- 浏览器接收到预检通过的响应后,开始向OBS服务端发送实际请求,其流程与简单请求的流程相同。
复制CORS规则
OBS支持通过控制台方式复制CORS规则,不支持通过API、SDK、OBS Browser+、obsutil方式复制CORS规则。
- 在OBS管理控制台左侧导航栏选择“桶列表”。
- 在桶列表中,单击待操作的桶,进入“对象”页面。
- 在左侧导航栏,单击“数据安全 > CORS规则”。
- 单击“复制”。
- 选择复制源,即CORS规则所在的源桶。
- 从源桶复制CORS规则的操作为增量复制,不会删除当前桶已存在的CORS规则,与已存在的CORS规则冲突的规则不会复制。
- 源桶和目标桶的桶版本号都必须是3.0。
- 单桶CORS规则上限为100条,如果已有规则+复制规则的数量超过上限,将会复制失败,请先删除多余规则再进行复制。
图2 复制CORS规则 
- 单击“确定”,将源桶的CORS规则复制到当前桶。
相关文档
CORS规则在其他重要场景的应用
- 安全要求高的场景
对安全要求较高的场景,建议您在配置CORS规则时,从“允许的来源”、“允许的方法”和“允许的头域”三个参数设置方面考虑:
- 准确配置“允许的来源”:如果桶不是完全公开被访问,不建议将“允许的来源”设置为“*”,应该精确配置网站域名。
- 缩小配置“允许的方法”:评估业务所需的请求方法,不多设置“允许的方法”。如:仅需通过网站查看桶中的图片,可以值设置“GET”和“HEAD”方法。
- 列出必要的“允许的头域”:遵循权限最小化,明确列出必须的请求头,避免使用通配符“*”。
- 性能要求高的场景
对性能要求高的场景,建议通过减少预检请求的次数来提高访问性能。
可以通过配置合理的“缓存时间”(如:86400秒)来减少预检请求的次数。
- 结合CDN的使用
如果桶开启了CDN加速并使用CDN域名访问桶,当跨域访问OBS时,请求会先到达CDN节点。此时有两种配置方式:
- 在CDN侧配置HTTP header,由CDN直接返回CORS头域,详见HTTP header配置。
- CDN直接透传OBS返回的CORS头域,此时需要在OBS侧配置CORS规则。
OBS侧的CORS规则仅在请求直接访问OBS源站域名或CDN直接透传OBS源站响应头时生效。
浏览器出现“No 'Access-Control-Allow-Origin' header is present on the requested resource”报错?
该报错表明浏览器没有找到带有“Access-Control-Allow-Origin”的响应头,可能是由于CORS规则中的来源配置有误导致请求无法匹配到,还有可能是由于浏览器缓存了不带“Access-Control-Allow-Origin”的旧的响应头。建议按如下步骤排查:
- 清除浏览器缓存后再重试。
- 如果清除浏览器缓存后问题不存在,说明是浏览器缓存导致的,为了避免后续问题再现,建议将CORS规则的“缓存时间”设置为“0”。
- 如果清除浏览器缓存后问题仍然存在,请执行2。
- 请检查CORS规则中的来源配置是否与跨域请求匹配。
- 如果不匹配,请修改CORS规则中的“允许的来源”。
- 如果匹配但仍然有问题,可能是由于OBS开启了CDN加速,请执行3。
- 排查CDN加速问题。
登录CDN控制台,临时取消CDN加速,确认问题是否仍然存在。
- 如果问题不存在,说明是为OBS桶配置了加速域名导致的,请在CDN加速域名的“高级配置”页签,配置自定义HTTP header。
- 如果问题仍然存在,请执行4。
- 请提交工单联系技术支持处理。
浏览器出现“The 'Access-Control-Allow-Origin' header has a value '...' that is not equal to the supplied origin”报错?
该报错表明OBS服务端返回了“Access-Control-Allow-Origin”响应头,但是其值和当前跨域请求的Origin不匹配。可能的原因是浏览器缓存导致的:当同一个桶配置了多条CORS规则,实现多个网站的跨域访问时,浏览器或CDN可能缓存了其他网站的Origin头。
解决办法:清除浏览器缓存后重新访问。
浏览器出现“The value of the 'Access-Control-Allow-Origin' header must not be the wildcard '*' when credentials mode is 'include'”报错?
该报错表明前端JavaScript代码发送了携带用户凭证信息的请求(Access-Control-Allow-Credentials: true),但在CORS规则中“允许的来源”被配置为通配符“*”。出于安全考虑,在使用凭证信息时,浏览器不允许使用通配符“*”来源。
解决办法:
- 如果需要在跨域请求中保留用户凭证信息,请将CORS规则中的“允许的来源”设置为具体域名,以及在“允许的头域”添加“Access-Control-Allow-Credentials: true”。
- 如果不需要在跨域请求中保留用户凭证信息,请在前端JavaScript代码中将“xhr.withCredentials”设置为“false”,并确保CORS规则中的“允许的头域”添加“Access-Control-Allow-Credentials: false”或不返回该头域。
设置“Access-Control-Allow-Credentials”头域为“true”可能会泄露用户凭证,增加安全风险,因此建议您不要设置该请求头为“true”。
OBS跨域访问慢如何提升访问速度?
OBS跨域访问速度取决于客户端到桶的物理链路,如果客户端和OBS桶存在远距离访问的情况,建议您使用为桶配置加速域名以提升访问OBS桶的速度,详情请参见通过CDN加速域名访问桶。
为OBS桶配置CDN加速域名后,建议您同时在CORS规则中开启“返回 Vary: Origin”,用于告知CDN等中间缓存需根据请求的Origin头来区分缓存版本,以避免多来源访问时的缓存错乱问题。