CORS是一个W3C标准,全称是"跨域资源共享" (Cross-origin resource sharing)
以往的解决方案
以前要实现跨域访问,可以通过JSONP、Flash或者服务器中转的方式来实现,但是现在我们有了CORS。
CORS与JSONP相比,无疑更为先进、方便和可靠。
1、 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。
2、 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。
3、 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS(这部分会在后文浏览器支持部分介绍)。
详细内容
要使用CORS,我们需要了解前端和服务器端的使用方法。
1、 前端
以前我们使用Ajax,代码类似于如下的方式:
- var xhr = new XMLHttpRequest();
- xhr.open("GET", "/hfahe", true);
- xhr.send();
这里的“/hfahe”是本域的相对路径。
如果我们要使用CORS,相关Ajax代码可能如下所示:
- var xhr = new XMLHttpRequest();
- xhr.open("GET", "http://www.liuxinxiu.com/hfahe", true);
- xhr.send();
请注意,代码与之前的区别就在于相对路径换成了其他域的绝对路径,也就是你要跨域访问的接口地址。
我们还必须提供浏览器回退功能检测和支持,避免浏览器不支持的情况。
- function createCORSRequest(method, url) {
- var xhr = new XMLHttpRequest();
- if ("withCredentials" in xhr) {
- // 此时即支持CORS的情况
- // 检查XMLHttpRequest对象是否有“withCredentials”属性
- // “withCredentials”仅存在于XMLHTTPRequest2对象里
- xhr.open(method, url, true);
- } else if (typeof!= "undefined") {
- // 否则检查是否支持XDomainRequest,IE8和IE9支持
- // XDomainRequest仅存在于IE中,是IE用于支持CORS请求的方式
- xhr = new XDomainRequest();
- xhr.open(method, url);
- } else {
- // 否则,浏览器不支持CORS
- xhr = null;
- }
- return xhr;
- }
- var xhr = createCORSRequest('GET', url);
- if (!xhr) {
- throw new Error('CORS not supported');
- }
现在如果直接使用上面的脚本进行请求,会看到浏览器里控制台的报错如下:
错误显示的很明显,这是因为我们还未设置Access-Control-Allow-Origin头。
2、 服务器
服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。
HTTP 头的设置方法有很多,http://enable-cors.org/这篇文章里对各种服务器和语言的设置都有详细的介绍,下面我们主要介绍Apache和PHP里的设置方法。
Apache:Apache需要使用mod_headers模块来激活HTTP头的设置,它默认是激活的。你只需要在Apache配置文件的<Directory>, <Location>, <Files>或<VirtualHost>的配置里加入以下内容即可:
- Header set Access-Control-Allow-Origin *
PHP:只需要使用如下的代码设置即可。
- <?php
- header("Access-Control-Allow-Origin:*");
以上的配置的含义是允许任何域发起的请求都可以获取当前服务器的数据。当然,这样有很大的危险性,恶意站点可能通过XSS攻击我们的服务器。所以我们应该尽量有针对性的对限制安全的来源,例如下面的设置使得只有http://www.liuxinxiu.com 这个域才能跨域访问服务器的API。
- Access-Control-Allow-Origin: http://www.liuxinxiu.com
浏览器支持情况