注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

老和山小和尚

敬天爱人

 
 
 

日志

 
 
 
 

Cross-Origin Resource Sharing协议的介绍  

2011-11-09 18:17:33|  分类: 协议研究 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

为什么要用COR(Cross-Origin-Request,跨域请求)?[1]

传统的Ajax请求只能获取在同一个域名下面的资源,但是HTML5打破了这个限制,允许Ajax发起跨域的请求。

浏览器是可以发起跨域请求的,比如你可以外链一个外域的图片或者脚本。但是Javascript脚本是不能获取这些资源的内容的,它只能被浏览器执行或渲染。

COR允许Javascript获取这些外域站点资源内容。

与crossdomain.xml的不同[1]

像Flash和Silverlight这类插件也允许读取跨域请求,但是它们的设计方式跟COR完全不同。

在Flash和Silverlight中,服务器需要创建一个crossdomain.xml的文件来允许跨域请求。如果这个文件声明“http://your.site”允许来自“http://my.site”的请求,则来自“http://my.site”的请求可以访问所有“http://your.site”的文件。这是一种整个站点层面上的控制模式,要么你允许一个外域的站点访问,要么拒绝。

COR不一样,它是页面层次的控制模式。每一个页面需要返回一个名为‘Access-Control-Allow-Origin’的HTTP头来允许外域的站点访问。你可以仅仅暴露有限的资源和有限的外域站点访问。在COR模式中,访问控制的职责可以放到页面开发者的手中,而不是服务器管理员。当然页面开发者需要写专门的处理代码来允许被外域访问。

另外一个主要的区别是,某个站点的crossdomain.xml文件是最早被浏览器获取并分析的。如果一个外域的站点不允许被访问,浏览器压根就不会发出跨域请求。

COR则相反,Javascript先发出跨域请求,然后检查回复的‘Access-Control-Allow-Origin’头。如果这个头允许该外域访问,则Javascript可以读取这个回复,否则就被禁止访问。如果请求不是一个简单的COR,则向外域服务器发送预检验请求,如果回复的头部允许访问,则发送跨域请求,否则禁止。

CORS(Cross-Origin Resource Sharing,跨域资源共享)协议的简单描述[2]
COR的实现标准就是CORS协议。

对于浏览器来说,COR请求都是Javascript发起的,COR请求有两种:
1、简单的COR请求,它可以直接向外域资源发起请求。它必须仅仅包含简单的方法和头,具体定义看[2] 6.1。
2、如果COR包含复杂的方法和头,它需要发出预检验(Preflight)请求,它先向资源服务器发出一个OPTIONS方法、包含“Origin”头的请求。该回复可以控制COR请求的方法,HTTP头以及验证等信息。只有该请求获得允许以后,才会发起真实的外域请求。

下面是一个简单的COR请求:
<script language="Javascript" type="text/javascript">
var client = new XMLHttpRequest();
client.open("GET", "http://bar.org/b")
client.onreadystatechange = function() { /* do something */ }
client.send()  
</script>

假设这个请求所在页面的域是“http://foo.org”。 如果来自“http://bar.org/b”的回复包含这样的头:

Access-Control-Allow-Origin: http://foo.org

则表明,它允许来自“http://foo.org”的跨域请求。


下面的Javascript会发出预检验请求和真实请求:
<script language="Javascript" type="text/javascript">
var client = new XMLHttpRequest();
client.open("GET", "http://bar.org/b")
client.setRequestHeader('Content-Type','text/html')
client.onreadystatechange = function() { /* do something */ }
client.send()  
</script>

由于“Content-type: text/html”不是一个简单的头,它会先向"http://bar.org/b"发出一个OPTIONS的HTTP请求。 回复可能包含这样的头:

Access-Control-Allow-Origin: http://foo.org 

Access-Control-Max-Age: 3628800 

Access-Control-Allow-Methods: GET,PUT, DELETE

Access-Control-Allow-Headers: content-type

"Access-Control-Allow-Origin"表明它允许"http://foo.org"发起跨域请求
"Access-Control-Max-Age"表明在3628800秒内,不需要再发送预检验请求,可以缓存该结果
"Access-Control-Allow-Methods"表明它允许GET、PUT、DELETE的外域请求
"Access-Control-Allow-Headers"表明它允许跨域请求包含content-type头

如果预检验请求获得通过,接下来Javascript就会发起真实的COR请求,过程跟简单的COR请求类似。

CORS协议的实现

现在HTML5的标准如火如荼的在制定和发展中,CORS作为HTML5的一部分,在大部分现代浏览器中有所支持,支持(部分支持)CORS协议的浏览器有IE8+, Firefox5+, Chrome12+, Safari4+ [4][5]。 让服务端支持CORS的方法有[6], 但这些支持都是部分的,没有完全实现CORS协议。

我已经在Nginx上完全实现了最新CORS协议的服务端部分,代码在这里[3]。由于CORS协议还处于草案阶段,浏览器和服务端都可能都会有变化。如果你发现我的模块与最新的协议冲突,可以与我联系。


参考资料:
[1] http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
[3] https://github.com/yaoweibin/nginx_cross_origin_module
  评论这张
 
阅读(3346)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017