Javascript Ajax总结——跨域资源共享

XHR对象只能访问与包含它的页面位于同一个中的资源。这种安全策略能够预防某些恶意行为。
CORS(Cross-Origin Resource Sharing,跨域资源共享)是W3C的一个工做草案,定义了在必须访问跨域资源时,浏览器与服务器应该如何沟通。CORS基本思想:使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功仍是失败。
如:一个使用GET或POST发送的请求,没有自定义的头部,主体内容是text/plain。发送请求时,须要给它附加一个额外的Origin头部,其中包含请求页面的源信息(协议、域名和端口),以便服务器根据这个头部信息来决定是否给与响应。

Origin头部如:
Origin: http://www.nczonline.net
若服务器认为这个请求能够接受,就在Access-Control-Allow-Origin头部中回发相同的源信息(如果公共资源,能够回发“*”)。如:
Access-Control-Allow-Origin: http://www.nczonline.net
若没有这个头部,或有这个头部但源信息不匹配,浏览器就会驳回请求。正常状况下,浏览器会处理请求。
注:请求和响应都不包含cookie信息。

一、IE对CORS的实现
微软在IE8中引入了XDR(XDomainRequest)类型,可以实现安全可靠的跨域通讯。XDR对象的安全机制部分实现了W3C的CORS规范。
XDR与XHR的一些不一样之处
* cookie不会随请求发送,也不会随响应返回。
* 只能设置请求头部信息中的Content-Type字段。
* 不能访问响应头部信息。
* 只支持GET和POST请求。
被请求的资源能够根据它认为合适的任意数据(用户代理、来源页面等)来决定是否设置Access-Control-Allow-Origin头部。做为请求的一部分,Origin头部的值表示请求的来源域,以便远程资源明确的识别XDR请求。
XDR对象的使用方法与XHR对象很是类似。也是建立一个XDomainRequest的实例,调用open()方法,再调用send()方法。但与XHR对象的open()方法不一样,XDR对象的open()只接收2个参数:请求的类型和URL。
全部XDR请求都是异步执行的。请求返回以后,会触发load事件,响应的数据也会保存在responseText属性中,如:
var xdr = new XDomainRequest();
xdr.onload = function(){
    alert(xdr.responseText);
};
xdr.open("get", "http://www.somewhere-else.com/page/");
xdr.send(null);

在接收到响应后,只能访问响应的原始文件,没有办法肯定响应的状态代码。并且只要响应有效就会触发load事件,若是失败就会触发error事件。遗憾的是,除了错误自己以外,没有其余信息可用,所以惟一可以肯定的就只有请求未成功了。要检测错误,能够指定一个onerror事件处理程序:
var xdr = new XDomainRequest();
xdr.onload = function(){
    alert(xdr.responseText);
};
xdr.onerror = function(){
    alert("An error occurred.");
};
xdr.open("get", "http://www.somewhere-else.com/page/");
xdr.send(null);

注:致使XDR请求失败的因素不少,因此建议经过onerror事件处理程序来捕获该事件;不然,即便请求失败也不会有任何提示。

在请求返回前调用abort()方法能够终止请求:
xdr.abort(); //终止请求
XDR对象也支持timeout属性以及ontimeout事件处理程序。如:
var xdr = new XDomainRequest();
xdr.onload = function(){
    alert(xdr.responseText);
};
xdr.onerror = function(){
    alert("An error occurred.");
};
xdr.timeout = 1000;
xdr.ontimeout = function(){
    alert("Request took too long.");
};
xdr.open("get", "http://www.somewhere-else.com/page/");
xdr.send(null);
运行1s后超时,并随机调用ontimeout事件处理程序。

为支持POST请求,XDR对象提供了contentType属性,用来表示发送数据的格式,如:
 1   var xdr = new XDomainRequest();
 2     xdr.onload = function(){
 3         alert(xdr.responseText);
 4     };
 5     xdr.onerror = function(){
 6         alert("An error occurred.");
 7     };
 8     xdr.open("post", "http://www.somewhere-else.com/page/");
 9     xdr.contentType = "application/x-www-form-urlencoded";
10     xdr.send("name1=value1&name2=value2");
这个属性是经过XDR对象影响头部信息的惟一方式。

二、其余浏览器对CORS的实现

 1 var xhr = createXHR();
 2 xhr.onreadystatechange = function(){
 3     if(xhr.readyState ==4){
 4         if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
 5             alert(xhr.responseText);
 6         }else{
 7             alert("Request was unsuccessful: " + xhr.status);
 8         }
 9     }
10 };
11 //跨域请求的url为绝对的连接
12 xhr.open("get", "http://www.somewhere-else.com/page/", true);
13 xhr.send(null);
限制:
* 不能使用setRequestHeader()设置自定义头部。
* 不能发送和接收cookie。
* 调用getAllResponseHeaders()方法总会返回空字符串。

对于本地资源,最好使用相对URL,访问远程资源时使用绝对URL,能够消除歧义,避免出现限制访问头部或本地cookie信息等问题。
三、跨浏览器的CORS
全部浏览器都支持简单的(非Preflight和不带凭据的)请求,所以有必要实现一个跨浏览器的方案。

 1 function createCORSRequest(method, url){
 2     var xhr = new XMLHttpRequest();
 3     if("withCredentials" in xhr){
 4         xhr.open(method, url, true);
 5     }else if(typeof XDomainRequest != "undefined"){
 6         xhr = new XDomainRequest();
 7         xhr.open(method, url);
 8     } else {
 9         xhr = null;
10     }
11     return xhr;
12  }
13 var request = cresteCORSRequest("get", "http://www.somewhere-else.com/page/");
14 if(request){
15     request.onload = function(){
16         //对request.responseText进行处理
17     };
18     request.send();
19 }
Firefox、Safari、Chrome中的XMLHttpRequest对象与IE中的XDomainRequest对象相似,都提供了够用的接口,所以以上模式仍是至关有用的。
这两个对象共同的属性/方法以下: * abort():用于中止正在进行的请求。 * onerror:用于替代onreadystatechange检测错误。 * onload:用于替代onreadystatechange检测成功。 * responseText:用于取得相应内容。 * send():用于发送请求。以上成员都包含在createCORSRequest()函数返回的对象中,在全部浏览器中都能正常使用。
相关文章
相关标签/搜索