跨域资源共享(1)
跨域资源共享
CORS(Cross-Origin Resource Sharing, 跨域资源共享)是W3C的一个草案,定义了在必须跨域访问资源时,浏览器与服务器如何沟通。其基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求是失败还是成功。
发送POST或GET请求时,没有自定义头部信息,主题内容为text/plain,需要添加一个额外的Origin头部,其中包含请求页面的源信息(协议、域名和端口)。
Origin : http://www.nczonline.net
如果服务器可以接受这个请求,就在Access-Control-Allow-Origin头部中回发相同的源信息,公共资源可以发回*
Access-Control-Allow-Origin : http://www.nczonline.net
请求和响应都不包含cookie信息
IE对CORS的实现
XDR类型:XDomainRequest
XDR与XHR的区别
- cookie不会随请求发送,也不会随响应返回
- 只能设置请求头部信息中的Context-Type字段
- 不能访问响应头部信息
- 只支持GET和POST请求
//GET请求
var xdr = new XDomainRequest();
xdr.onload = function() {
alert(xdr.responseText);
}
xdr.onerror = function() {
alert("An error occured");
}
xdr.timeout = 1000;
xdr.ontimeout = function() {
alert("Request took too long");
}
xdr.open("get","http://example.com/page/");
//xdr.open("post","http://example.com/page/");
//xdr.contentType = "application/x-www-form-urlencoded";
xdr.send(null);
- XDR使用方法和XHR类似,先创建一个XDomianRequest对象,调用open方法,再调用send方法
- XDR的open方法只支持两个参数,请求方式和URL
- XDR请求都是异步的,不能创建同步请求
- 请求返回后,触发onload事件,响应的事件也会保存在responseText属性中
- 响应如果失败,就会触发error事件,但是除了错误本身外,没有任何其他信息
- 在请求返回前可以使用abort()方法终止请求
- 与XHR一样,XDR也支持timeout属性以及ontimeout事件处理程序
- 对于POST请求,提供了contentType属性,用来表示发送数据的格式
其他浏览器对CORS的支持
FireFox 3.5+、Safari 4+、Chrome、iOS版Safari和Andriod平台中的Webkit都通过XHR对象实现了对CORS的原生支持,使用标准XHR对象并在open方法中传入绝对URL即可
var xhr = createXHR();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText);
} else {
alert("Request was unsuccessful : " + shr.status);
}
}
}
xhr.open("get","http://www.somewhere-else.com/page/", true);
xhr.send(null);
Preflighted Requests
CORS通过一种叫做Preflighted Requests的透明服务器验证机制支持开发人员使用自定义的头部、GET或POST之外的方法,以及不同类型的主题内同,在使用下列高级选项来发送请求时,就会向服务器发送一个Preflight请求,这种请求使用OPTIONS方法,发送以下头部
- Origin:与简单的请求相同
- Access-Control-Request-Method:请求自身使用的方法
- Access-Control-Request-Headers:(可选)自定义的头部信息,多个头部以逗号隔开
Origin: http://www.nczonline.net
Access-Control-Request-Method:POST
Access-Control-Request-Headers:NCZ
发送请求后,服务器可以决定是否允许这种类型的请求,服务器通过在襄阳中发送如下头部与浏览器进行沟通
- Access-Control-Allow-Origin:与简单请求相同
- Access-Control-Allow-Method:允许的方法,多个方法用逗号隔开
- Access-Control-Allow-Headers:允许的头部,多个头部用逗号隔开
- Access-Control-Max-Age:应该将这个Prefilght请求缓存多长时间(以秒记)
Access-Control-Allow-Origin: http://www.nczonline.net
Access-Control-Allow-Method:POST, GET
Access-Control-Allow-Headers:NCZ
Access-Control-Max-Age:1728000
带凭据的请求
默认情况下,跨域请求不提供凭据(cookie,HTTP认证及客户端SSL证明等),通过将withCredentials属性设置为true,可以指定某个请求应该发送凭据,如果服务器接受带平局的请求,会用下面的HTTP头部来响应
Access-Control-Allow-Credentials:true
跨浏览器的CORS
检查XHR是否支持CORS最简单的方法就是检查是否存在withCredentials属性,再结合检测XDR是否存在,就可以兼顾所有浏览器了
function createCORSRequest(method,url){
var xhr = new XMLHttpRequest();
//检查是否支持CORS
if("withCredential" in xhr){
xhr.open(method,url,true);
} else if (typeof XDomainRequest != "undefined"){
xhr = new XDomainRequest();
xhr.open(method,url);
} else {
xhr = null;
}
return xhr
}
var request = createCORSRequest("get","http://www.somewhere-else.com/page/");
if(request){
request.onload = function(){
//对request.responseText进行处理
}
request.send();
}
xhr与xdr的共同属性/方法:
- abort()
- onerror()
- onload()
- responseText
- send()