同源策略限制从一个源加载的文档或脚本与来自另一个源的资源进行交互的方式,是用于隔离潜在恶意文件的关键安全机制。同协议、同域名(或 IP)、以及同端口视为同一个域,一个域内的脚本仅仅具有本域内的权限,即本域脚本只能读写本域内的资源,而无法访问其它域的资源。这种安全限制称为同源策略。
两个页面的协议、域名和端口(若指定了端口)相同,则视为同源。如下表给出了相对http://www.example.com/dir/page.html的同源检测示例:
| URL | 结果 | 原因 |
http://www.example.com/dir2/other.html | 成功 | 协议、域名、端口相同 |
http://www.example.com/dir/inner/another.html | 成功 | 协议、域名、端口相同 |
https://www.example.com/secure.html | 失败 | 协议不同 ( HTTPS ) |
http://www.example.com:81/dir/etc.html | 失败 | 端口不同 ( 81 ) |
http://news.example.com/dir/other.html | 失败 | 域名不同 |
跨域资源共享(Cross-Origin Resource Sharing,CORS)机制,我们简称为跨域访问,允许 Web 应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE 浏览器要求版本 IE10 或以上。整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS 通信与同源的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户无感知。因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,即可跨源通信。
用户在使用浏览器的情况下会使用到 CORS,因为控制访问权限的是浏览器而非服务器。因此使用其它客户端的时候无需关心任何跨域问题。CORS 的主要应用是实现在浏览器端使用 AJAX 直接访问 COS 的数据或上传、下载数据,而无需通过用户本身的应用服务器中转。对于同时使用 COS 和使用 AJAX 技术的网站,建议使用 CORS 来实现与 COS 的直接通信。
COS 支持对 CORS 规则的配置,从而根据需求允许或者拒绝相应的跨域请求。该 CORS 规则配置属于存储桶级别。CORS 请求的通过与否和 COS 的身份验证等是完全独立的,即 COS 的 CORS 规则仅仅是用来决定是否附加 CORS 相关的 Header 的一个规则。是否拦截该请求完全由浏览器决定。目前 COS 的所有 Object 相关接口都提供了 CORS 相关的验证,另外 Multipart 相关的接口目前也已经完全支持 CORS 验证。说明:当同一个浏览器上的分别来源于www.a.com和www.b.com的两个页面同时请求同一跨域资源时,若www.a.com的请求先到达服务器,服务器会将资源带上 Access-Control-Allow-Origin 的 Header,并返回给www.a.com的用户。这时www.b.com又发起了请求,浏览器会将 Cache 的上一次请求响应返回给用户,Header 的内容和 CORS 的要求不匹配,就会导致www.b.com请求失败。
以下简单示例介绍使用 AJAX 从 COS 获取数据的配置步骤。示例中使用的存储桶(Bucket)权限设置为公有(Public),访问权限为私有的存储桶(Bucket)只需要在请求中附加签名,其余配置相同。 以下示例中使用的存储桶名为 corstest-125xxxxxxx,存储桶访问权限为公有读私有写。
1. 确认文件可正常访问 上传一个 test.txt 的文本文档(内容为test)到存储桶 corstest-125xxxxxxx。test.txt 的访问地址为http://corstest-125xxxxxxx.cos.ap-beijing.myqcloud.com/test.txt。 使用 curl 直接访问该文本文档,请将以下地址替换为您的文件地址:
curl http://corstest-125xxxxxxx.cos.ap-beijing.myqcloud.com/test.txt
返回 test.txt 文件的内容:test。表示该文档可以正常访问。
<!doctype html><html><head><meta charset="UTF-8"></head><body><a href="javascript:test()">Test CORS</a><script>function test() { var url = 'http://corstest-125xxxxxxx.cos.ap-beijing.myqcloud.com/test.txt'; var xhr = new XMLHttpRequest(); xhr.open('HEAD', url); xhr.onload = function () { var headers = xhr.getAllResponseHeaders().replace(/\r\n/g, '\n'); alert('request success, CORS allow.\n' + 'url: ' + url + '\n' + 'status: ' + xhr.status + '\n' + 'headers:\n' + headers); }; xhr.onerror = function () { alert('request error, maybe CORS error.'); }; xhr.send();}</script></body></html>
2.2 在浏览器中打开该 HTML 文件,单击 Test CORS 发送请求后,出现以下错误,错误提示:无权限访问,原因是没有找到 Access-Control-Allow-Origin 这个 Header。显然,这是因为服务器没有配置 CORS。 http://127.0.0.1:8081,所以 Origin 是http://127.0.0.1:8081。若您的网页未搭建在服务器上,使用本地浏览器打开,Origin 是 null。
确定访问不成功的原因之后,可以通过设置存储桶相关的 CORS 来解决以上问题。COS 控制台可以进行 CORS 设置,本示例使用控制台来完成 CORS 的设置。若您的 CORS 设置不是特别复杂,也建议使用控制台来完成 CORS 设置。1. 登录 COS 控制台 ,单击存储桶列表,进入相关的存储桶,单击安全管理页签,下拉页面即可找到“跨域访问 CORS 设置”。2. 单击添加规则,添加第一条规则,使用最宽松的配置如下:
注意:CORS 设置是由一条一条规则组成的,会从第一条开始逐条匹配,以最早匹配上的规则为准。关于 CORS 配置项说明请参见 设置跨域访问。
配置完成后,重新尝试访问 test.txt 文本文件。结果如下,可以正常访问请求。
若想要排除跨域带来的访问问题,可以将 CORS 设置为以上最宽松的配置,该配置允许所有的跨域请求。该配置下依然出错,则表明错误出现在其他部分而不是 CORS。除了最宽松的配置之外,您还可以配置更精细的控制机制来实现针对性的控制。例如,对于本示例可以使用如下最小的配置匹配成功: