跨域解决方案CORS
现在来讲,比较常见的跨域解决方案是通过jsonp,flash来实现的跨域访问问题。
传统的JSONP
在web页面中,具有src属性的标签不受同源策略的影响,可以跨域访问很多资源,这也是很多开发者喜欢引用一些cdn服务器的框架脚本库的一个组成吧。JSON被用来描述复杂的数据, 客户端通过传递一个回调函数的作为一个参数给跨域服务器,跨域服务器在处理数据后,用这个callback包裹待调用的JSON数据,通过返回一个动态脚本来即时执行这个回调函数,来达到跨域访问并调用返回数据的目的
CORS
CORS是一个更为新颖的解决方案,Cross-Origin Resource Sharing, 目前CORS还处于w3c的草案,它定义了跨域访问时服务器和客户端之间如何通信。他的原理是通过定义HTTP头部的信息,来让客户端和服务器互相确认,从而决定是否相应本次请求。
CORS和JSONP相比,更为方便,是否更为安全有待验证!
1: JSONP目前只支持get请求,因为它是通过模拟src资源访问的方式进行请求,而CORS支持了所有的HTTP请求类型,它从通过定义HTTP头文件信息决定请求,所以可以指定请求类型
2:使用CORS,web开发者可以使用普通的XMLHttpRequest,来发起请求,当然现在的JSONP方案已经相对成熟,大部分的第三方脚本框架都进行了封装支持,但使用CORS应该具有更好的容错机制。
下面详细说明下如何使用CORS:
1 web端: 同普通的XMLHttpRequest 相差无几
var xhr = new XMLHttpRequest(); xhr.open("GET", "http://xxx.a.com", true); xhr.send();
这里需要指定绝对路径(因为你要跨域, 相对地址明显不行)
兼容性:老的浏览器是不支持CORS的
我们可以使用特性探测的方式来做兼容性测试, "withCredentials" 这个特性就存在于XMLHttpRequest2中,这个是用来在发送跨域请求的凭据,模式这个属性会是false,当设置为true时会自动带上cookie,当然cookie依然遵守同源策略的规则,你不可访问。我们这里只是用于特性探测,暂时不需要设置
function compatibleCORS(method, url) { var xhr = new XMLHttpRequest(); if ("withCredentials" in xhr) { xhr.open(method, xhr, true); } else if (typeof XDomainRequest != "undefined") { //XDomainRequest是IE用于支持CORS请求的对象 xhr = new XDomainRequest(); xhr.open(method, xhr); } else { xhr = null; } return xhr; } var xhr = compatibleCORS('GET', "http://xxxxxxx"); if (!xhr) { throw new Erorr("CORS不被支持"); }
2: 服务端
如果此时直接用上面的js发送请求,服务器是不会响应该请求的,会报Access-Control-Allow-Origin 的错误。为了安全策略,一定要在服务端指定一个白名单,而不是使用泛匹配的方式(*号) Access-Control-Allow-Origin: www.xxx.com
PS: 如果要带上cookie做用户凭据,则还需要设置Access-Control-Allow-Credentials: true
关于服务器端如何设置,需要看什么服务器端,网上有很多相关的设置方式,这里不在叙述
浏览器的支持情况可以去这里查看http://caniuse.com/cors