专栏首页张善友的专栏Cross-Origin Resource Sharing协议介绍

Cross-Origin Resource Sharing协议介绍

传统的Ajax请求只能获取在同一个域名下面的资源,但是HTML5打破了这个限制,允许Ajax发起跨域的请求。浏览器是可以发起跨域请求的,比如你可以外链一个外域的图片或者脚本。但是Javascript脚本是不能获取这些资源的内容的,它只能被浏览器执行或渲染。

在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,则向外域服务器发送预检验请求,如果回复的头部允许访问,则发送跨域请求,否则禁止。

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+

服务端实现

Thinktecture.IdentityModel  这个库已经为我们的WebAPI,MVC的项目做好了支持,具体参看[6]。

参考资料:

[1] http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity

[2] http://www.w3.org/TR/cors/

[3]Cross-origin_resource_sharing

[4]跨域资源共享(Cross-Origin Resource Sharing)实现Ajax跨域请求

[5]http://restfulobjects.codeplex.com/wikipage?title=Cross%20Origin%20Resource%20Sharing&referringTitle=Documentation

[6]CORS support in WebAPI, MVC and IIS with Thinktecture.IdentityModel

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Wix 3.0支持Windows Installer 5.0

     Windows Vista 和SP 1, Windows XP SP3, Windows Server 2008 RTM/SP1, Windows Serve...

    张善友
  • .NET Core系列 : 2 、project.json 这葫芦里卖的什么药

    .NET Core系列 : 1、.NET Core 环境搭建和命令行CLI入门 介绍了.NET Core环境,本文介绍.NET Core中最重要的一个配置文件p...

    张善友
  • 如何在程序中加入Growl通知

    Growl for Windows – Mac 样式的信息提示工具。目前已经支持的软件包括:Outlook,Visual Studio 等以及一个利用命令行从本...

    张善友
  • 揭秘简单请求与复杂请求

    开发网站时经常会用到跨域资源共享(简称cors,后面使用简称)来解决跨域问题,但是在使用cors的时候,http请求会被划分为两类,简单请求和复杂请求,而这两种...

    挥刀北上
  • 关于Laravel下Cors跨域POST请求的一种实现方法

    之前做了一个公司的内部管理系统,现在希望通过在钉钉上开发一个小应用查看相关数据,在此过程中涉及了HTTP的跨域请求的问题,在了解相关信息后,打算基于CORS实现...

    前端博客 : alili.tech
  • javaWeb idea学习笔记(四)HTTP

    User-Agent:浏览器告诉服务器,浏览器访问服务器使用的版本信息,可以在服务器端去获取该头的信息来解决浏览器的兼容性问题。

    逆回十六夜
  • 从零实现一个http服务器

    我始终觉得,天生的出身很重要,但后天的努力更加重要,所以如今的很多“科班”往往不如后天努力的“非科班”。所以,我们需要重新给“专业”和“专家”下一个定义:所谓专...

    范蠡
  • Spring Boot中通过CORS解决跨域问题

    很多人对跨域有一种误解,以为这是前端的事,和后端没关系,其实不是这样的,说到跨域,就不得不说说浏览器的同源策略。 同源策略是由Netscape提出的一个著名的安...

    江南一点雨
  • DeepMind人工智能系统可有效处理50多种眼科疾病

    【概要】谷歌旗下的DeepMind公司联合多家研究机构所开发出来的一套人工智能系统可以有效处理50多种眼科疾病,可与优秀的人类专家媲美。

    人工智能快报
  • HTTP之跨域预请求options

    然后node server.js,打印出listen port 300表示启动成功,接着写一个Ajax请求:

    wade

扫码关注云+社区

领取腾讯云代金券