跨资源共享

CORS定义

通过XHR实现Ajax通信的一个主要限制,来源于跨域安全策略。默认情况下,XHR对象只能访问与包含他的页面位于同一个域中的资源。

CORS(Cross-Origin Resource Sharing,跨源资源共享)定义了在必须访问跨源资源时,浏览器和服务器间的沟通方式。

CORS的基本思想:使用自定义的HTTP头部让浏览器与服务器进行沟通,从而确定请求或响应是应该成功,还是应该失败。

比如一个简单的使用GET或POST发送的请求,它没有自定义的头部,而主体内容是text/plain。在发送该请求是,需要给它附加额外的Origin头部,其中包含请求页面的源信息(协议、域名和端口),以便服务器根据这个头部信息来决定是否给予响应。

下面是Origin头部的一个示例:
Origin:http://www.helloworld.net

如果服务器认为这个请求可以接受,就在Access-Control-Allow-Origin头部中回发相同的源信息(如果是公共资源,可以回发“*”)。

例如: Access-Control-Allow-Origin:http://www.helloworld.net

如果没有这个头部,或者有这个头部但源信息不匹配,浏览器就会驳回请求。正常情况下,浏览器就会处理请求。注意,请求和响应都不包含cookie信息。

Preflighted Requests

CORS通过一种就做Preflighted Requests 的透明服务器验证机制支持开发人员使用自定义的头部、GET或POST之外的方法,以及不同类型的主体内容。在使用下列高级选项来发送请求时们就会向服务器发送一个preflight请求。
这种请求使用OPTIONS方法,发送下列头部

  • origin: 源信息
  • Access-Control-Request-Method: 请求自身使用的方法
  • Access-Control-Request-Headers: (可选)自定义的头部消息,多个头部以逗号分隔。
    以下是一个带有自定义头部NCZ的使用POST方法发送的请求。

Origin: http://www.helloworld.net
Access-Control-Request-Method: POST
Access-Control-Request-Headers: NCZ

发送这个请求后,服务器可以决定是否允许这种类型的请求。服务器通过在响应中发送如下头部与浏览器进行沟通。
Access-Control-Allow-Origin: 服务器可以接受的源信息
Access-Control-Allow-Methods:允许的方法,多个方法以逗号分隔
Access-Control-Allow-Headers: 允许的头部,多个头部以逗号分隔
Access-Control-Max-Age: 应该将这个preflight请求缓存多长时间(以秒表示)

例如:
Access-Control-Allow-Origin: http://www.helloworld.net
Access-Control-Allow-Methods: POST,GET
Access-Control-Alloe-Headers: NCZ
Access-Control-Max-Age:172800

Prefight请求结束后,结束将按照响应中指定的时间缓存起来。而为此付出的代价只是第一次发送这种请求时会多发一次HTTP请求。

带凭据的请求

默认情况下,跨源请求不提供凭据(cookie、HTTP认证及客户端SSL证明等)。通过将withCredentials属性设置为true,可以指定某个请求应该发送凭证。如果服务器接受带凭据的请求,会用下面的HTTP头部来响应。
Access-Control-Allow-Credentials: true

如果发送的是带凭据的请求,但服务器的响应中没有包含这个头部,那么浏览器就不会把响应交给JavaScript(于是,responseText中将是空字符串,status的值为0,而且会调用onerror( )事件处理程序)。另外,服务器还可以在preflight响应中发送这个HTTP头部,表示允许源发送带凭据的请求。

跨浏览器的CORS

即使浏览器对CORS的支持程度不都一样,单所有浏览器都支持简单的(非Preflight和不带凭据的)请求,因此有必要实现一个跨浏览器的方案。检测XHR是否支持CORS的简单方式,就是检查是否存在withCredentials属性。再结合检测XDomainRequest对象是否存在,就可以兼顾所有的浏览器了。

function createCORSRequest(method ,url){
var xhr = new XMLHttpRequest( );
 if ( "withCredentials"  in xhr){
	xhr.open( method , url , true)
 }else if( typeof XDomainRequest !== "undefined"){//IE浏览器
 	xhr = new XDomainRequest( );
 	xhr.open(method , url);
 }else{
    xhr = null;
 }
 	return xhr;
}

var request = createCORSRequest( "get", "http://www.helloworld");
if(request){
	request.onload = function(){
	//对request.responseText 进行处理
	};
	request.send( )
}

Firefox、Safari和Chrome中的XMLHttpRequest对象与IE中的XDomainRequest对象类似,都提供了够用的接口,因此以上模式还是相当有用的。这两个对象共同的属性/方法如下。

  • abort( ) 用于停止正在进行的请求
  • onerror 用于替代onreadystatechange检测错误
  • onload 用于替代onreadystatechange检测成功
  • responseText 用于取得相应内容
  • send() 用于发送请求中
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值