跨域一直以来都是个非常神奇,又非常普遍的问题。出于安全等因素的考虑,通常情况下,浏览器通常会仅限制资源的访问,XHR(Ajax)的跨域请求是不被允许的。

但跨域的需求却一直都在,为了跨域,勤劳勇敢的程序猿们想出了许许多多的方法,例如,jsonP、代理文件等等。但这些做法增加了许多不必要的维护成本,而且应用场景也有许多限制,例如jsonP并非XHR,所以jsonP只能使用GET传递参数。

在移动应用风生水起的如今,托HTML5的福,Mobile Web,甚至Hybird App也逐渐火起来,在本地文件系统的Web页面,也有需要获取外部数据的需求,而这些需求也必然是跨域的。同时,HTML5也来带了叫“Cross-Origin Resource Sharing”的新特性,来赋予开发者权力决定资源是否允许被跨域访问。

Access-Control-Allow-Origin
CORS通过服务器增加一个特殊的Header[Access-Control-Allow-Origin]来告知客户端跨域的限制,如果浏览器支持CORS的话,如果判断Origin通过的话,就会允许XHR进行请求,而不需要再使用jsonP或者代理文件。

使用这个Header返回被允许请求跨域请求的来源域,例如网站duelist.cn设置了下面的Header
Access-Control-Allow-Origin: http://smdcn.net
这样设置之后,通过http://smdcn.net下的页面对于duelist.cn进行ajax请求就会被允许,而其他网站对duelist.cn依旧会被阻拦,通过这种方式网站拥有者可以自己对此进行限制。

当然,如果不想限制来源,可以通过
Access-Control-Allow-Origin: *
来允许任何站点对该资源进行跨域请求


关于CORS的浏览器支持情况(caniuse cors):
Can I use CORS
* 主流的移动浏览器:√

如果想要需要对于IE8和9支持CORS:可以使用jquery.iecors


设置CORS
对于客户端来说,一般来说不需要进行额外的设置,只要保证浏览器支持CORS即可
对于服务端,需要给支持CORS的资源增加Access-Control-Allow-Origin的Header。
可以通过HTTP服务器进行统一的Header设置,如果执行的是程序脚本,也可以在程序脚本中加入。
例如,PHP的话,使用

Header(“Access-Control-Allow-Origin:*”);

更多关于CORS的使用参考:http://enable-cors.org/


关于Android浏览器的注意事项
在某些版本的Android浏览器中,因为缓存的原因,第一次进行CORS是正常的,但是第二次进行的时候则会失效,对于这个问题,可以通过在Header中增加Cache-Control: no-cache 阻止缓存的方式来解决这个问题


关于跨域请求读取Cookie的需求
CORS的跨域请求默认情况下不发送本地cookie,同时也不接受来自服务器的cookie。
在跨域请求中读写Cookie并不被推荐,但是如果非要使用Cookie的话,需要在服务端返回是增加Header:

Access-Control-Allow-Credentials:true

同时ajax请求时,对XMLHttpRequest对象设置withCredentials = true;

var xhr = new XMLHttpRequest();
xhr.open();
xhr.withCredentials = true;