跨源资源共享
Web 发展早期使用
FlashJava applet这些中间件实现跨源资源共享;在 Ajax 出现之前还有使用内嵌框架、多窗口实现跨源资源共享的
hack方案;浏览器本地对不同域资源的共享存在限制;
关闭 Chrome 的同源政策:链接
Ajax实现跨域资源共享的前提是:得到目标域对本域的许可(Access-Control-Allow-Origin),服务器未做过多地限制。
IE 对 CORS 的实现
微软在 IE 8 中引入
XDR(XDomainRequest)类型,与XHR对象类似,但能实现可靠的跨域通信;XDR在实现跨域通信的同时,同时对于安全性做了以下限制cookie不会随之发送,也不会随响应返回 -- 防止 cookie 盗用- 只能设置请求头部信息中的
Content-Type-- 防止欺骗浏览器 - 不能访问响应头部信息
- 只支持
GET和POST请求
被请求的资源 服务器 可以根据它认为合适的任意数据(用户代理、来源页面等)来 决定是否设置
Access-Control-Allow-Origin头部。作为请求头的一部分,Origin的值表示请求的来源域XDR对象的使用方法与XHR对象非常相似- 先实例化一个
XDR对象 open()- 参数一:请求类型(只支持
GET和POST) - 参数二:
URL
- 参数一:请求类型(只支持
send()- 参数:需要传送的数据
- 先实例化一个
请求的返回值与事件处理程序:
- 请求返回之后会触发
load事件; - 如果请求失败(包括响应中缺少
Access-Control-Allow-Origin头)会触发error事件; - 响应的数据保存在
responseText属性中; - 请求返回前可以使用
abort()方法终止请求; XDR对象也支持timeout对象以及ontimeout事件处理程序;XDR对象提供了contentType属性用来表示发送数据的格式(主要针对 POST 请求)。
- 请求返回之后会触发
其他浏览器对 CORS 的实现
基本现代浏览器都通过
XMLHttpRequest对象实现了对CORS原生支持;前提仍旧是目标域未对资源做限制(对来源域开放,能为其设置
Access-Control-Allow-Origin头);跨域
XHR对象的限制- 不能使用
setRequestHeader()设置自定义头部; - 不能发送和接收
Cookie(需特殊设置,见下放withCredentials); - 调用
getAllResponseHeader()方法总是返回空字符串。
- 不能使用
最佳实践:对于同源的本地资源,最好使用相对
URL,在访问远程资源时再使用绝对URL这样做能消除歧义,避免出现限制访问头部或本地
Cookie信息等问题
Preflighted Requests
CORS的Preflighted Requests机制会在使用以下高级选项时触发- 自定义的头部
GET和POST之外的方法- 不同类型的主体内容
Preflighted Requests只是在正式发起请求之前的一次预请求,用于确认服务器支持的- 域
- 请求方法
- 自定义头
Preflighted Requests是触发之后由浏览器自动发起的,我们无需额外的操作;Preflighted Requests使用OPTIONS方法的请求头Origin: http://ce.sysu.edu.cn Access-Control-Request-Method: POST Access-Control-Request-Headers: DITHeader支持
Preflighted Requests请求的服务器返回的响应头Access-Control-Allow-Origin: * Access-Control-Allow-Methods: POST, GET Access-Control-Allow-Headers: DIYHeader Access-Control-Max-Age: 1728000对一个目标域只需要一次
Preflighted Requests,预请求的响应会按照响应头的Access-Control-Max-Age规定的时间来缓存。
带凭据的请求
默认情况下,跨域请求不支持提供凭据(
cookie、HTTP认证以及客户端SSL证明);通过将
XHR对象的widthCredentials属性设置为true,可以指定XHR对象发送请求时携带凭据;要使请求携带凭据的前提:服务器接受带凭据的请求,并且响应头包含下列名值对
Access-Control-Allow-Credentials: true如果发送的是带凭据的请求,但服务器的响应中没有包含上面的头部信息,那么浏览器就不会把响应交给
JavaScript,这样responseText就为空,status的值为 0,并且会触发XHR对象的onerror()事件;服务器可以在响应
Preflighted Requests的响应头中发送上面这个头部,表示允许源发送带凭据的请求。
跨浏览器的 CORS
即在版本的 IE 中(IE 8-)中需要跨域时,使用 XDR 对象。
见红书:P583