跨源资源共享-CORS(A.K.A.跨域AJAX请求)是大多数web开发人员可能遇到的问题,根据同源策略,浏览器在安全沙盒中限制客户端JavaScript,通常JS无法直接与来自不同域的远程服务器通信。过去,开发人员创建了许多复杂的方法来实现跨域资源请求,最常用的方法是:
使用Flash/SSilverlight或服务器端作为“代理”进行通信使用遥控器。带填充的JSON(JSONP)。在iframe中嵌入远程服务器,并通过fragment或window.name进行通信,请参阅此处。
这些棘手的方法或多或少都有一些问题,例如,如果开发人员简单地“评估”JSONP,JSONP可能会导致安全漏洞,而上面的第3条,虽然它有效,但两个域之间应该建立严格的契约,它既不灵活也不优雅IMHO:)
W3C引入了跨源资源共享(CORS)作为标准解决方案,以提供一种安全、灵活和推荐的标准方式来解决这个问题。
机制
从高层次上讲,我们可以简单地将CORS视为来自域a的客户端AJAX调用与域B上托管的页面之间的契约,典型的跨源请求/响应将是:
DomainA AJAX请求标头
Host DomainB.com
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json
Accept-Language en-us;
Accept-Encoding gzip, deflate
Keep-Alive 115
Origin http://DomainA.com
DomainB响应标头
Cache-Control private
Content-Type application/json; charset=utf-8
Access-Control-Allow-Origin DomainA.com
Content-Length 87
Proxy-Connection Keep-Alive
Connection Keep-Alive
上面我标记的蓝色部分是核心事实,“Origin”请求头“表示跨源请求或飞行前请求的来源”,“Access Control Allow Origin”响应头表示此页面允许来自DomainA的远程请求(如果值为*,则表示允许来自任何域的远程请求)。
如上所述,W3建议浏览器在提交实际的跨源HTTP请求之前实现一个“预飞行请求”,简而言之,这是一个HTTP OPTIONS请求:
OPTIONS DomainB.com/foo.aspx HTTP/1.1
如果foo.aspx支持OPTIONS HTTP动词,它可能会返回如下响应:
HTTP/1.1 200 OK
Date: Wed, 01 Mar 2011 15:38:19 GMT
Access-Control-Allow-Origin: http://DomainA.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, HEAD
Access-Control-Allow-Headers: X-Requested-With
Access-Control-Max-Age: 1728000
Connection: Keep-Alive
Content-Type: application/json
只有当响应包含“Access Control Allow Origin”且其值为“*”或包含提交CORS请求的域时,通过满足此强制条件,浏览器才会提交实际的跨域请求,并将结果缓存在“Preflight result cache”中。
三年前,我在博客中写到了CORS:AJAX跨源HTTP请求