跨域解决方案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

posted @ 2014-01-13 13:02  爵爷Jarvis  阅读(433)  评论(0编辑  收藏  举报