jQuery的剑道UI?下载30天免费试用

CORS数据获取

本文作者:Todd Anglin最初发表在剑道UI博客于2011年10月3日发布,并于2012年7月更新。

为了保持一致性,这里保留了条目的原始拼写、语法和结构。

在所有(现代)浏览器中使用CORS

跨地域资源共享是一种(缓慢)新兴的web技术,最终提供了一种直接从不同域获取资源的异步web操作方法。事实上,我们已经在剑道UI博客上讨论过CORS几次了在这里而且在这里

默认情况下,同源所有浏览器内置的安全沙箱不允许跨不同域调用XHR (Ajax)。你可以尝试一下,但是你会得到一个类似这样的错误:

XMLHttpRequest无法加载[URL]。Access-Control-Allow-Origin不允许Origin[您的网站]。

这条消息基本上是说您不能使用Ajax从不同的域加载资源。但最后的误差是什么呢?

Access-Control-Allow-Origin

CORS的工作原理是在从服务器到客户端的响应中添加一个特殊的报头。如果响应包含Access-Control-Allow-Origin如果浏览器支持CORS,那么就有机会直接使用Ajax&dmash加载资源;不需要代理或JSONP黑客

为什么只是一个机会?

标头能够指定允许哪些远程站点加载跨源资源。例如,在一个假设的响应中考虑以下CORS头:Access-Control-Allow-Origin [http://htmlui.com] (http://htmlui.com/)

使用此配置,只有起源于http://htmlui.com允许从哪里加载资源telerik.com.试图使用Ajax从其中加载资源的任何其他域telerik.com将给出标准的安全错误消息。通过这种方式,站点所有者可以限制允许哪些域使用CORS加载其资源。

或者,网站所有者可以授予完全开放的访问权限,并标注“随时准备参加聚会”星号:__Access-Control-Allow-Origin: * __

现在,任何想要直接使用Ajax加载资源的站点都可以这样做,而不会出现浏览器安全错误。这项技术对于经常使用JavaScript加载数据的现代应用程序很有帮助,而且越来越多的现代web api正在考虑支持CORS。要查看CORS的运行情况,请参见GeoNames.orglast . fm,谷歌api。

服务器端设置

显然,CORS是强大的。它打开了严格控制的浏览器安全沙箱,这对受信任的网络结构至关重要。正如你所期望的那样,这是一个必须由网站所有者做出的决定(你不能在不允许使用CORS的网站上使用它),它由web服务器配置控制。

任何人都可以通过简单地让web服务器添加必要的cors来启用他们的站点Access-Control-Allow-Origin头。事实上,有一个完整的网站致力于向你展示如何为不同的web服务器主机添加此标头。在Apache中,只需将这一行添加到htaccess文件头设置Access-Control-Allow-Origin *

处理浏览器

使用浏览器从来都不简单,特别是当您希望确保广泛的兼容性时。

经证实是有用的CanIUse.com在美国,对CORS的支持是一个大杂烩。CORS已经100%准备就绪:

  • WebKit浏览器(Chrome, Safari, iOS, Android)
  • 壁虎浏览器(Firefox)
  • Trident浏览器(Internet Explorer 8+)
  • 快速浏览器(特别是Opera 12+)

还不错。直到最近,Opera才从这个名单中消失,但随着2012年年中Opera 12的发布,Opera现在也支持CORS

我们将在一分钟内讨论如何处理旧的Opera版本,但让我们首先讨论IE。

Internet Explorer和XDomainRequest

IE10之前的ie浏览器在跨源资源共享方面稍有不同。ie8和ie9没有走WebKit和Gecko的路线,而是没有重用标准AjaxXMLHttpRequest对象用于CORS请求。相反,它们为跨起源资源共享引入了一个全新的对象XDomainRequest

这意味着跨域调用的Ajax代码看起来100%相同同一域在Chrome和Firefox中调用,但它将不得不在Internet Explorer中使用新的XDR对象和CORS请求。痛苦,但却是可以解决的问题。XDR还有其他一些限制,但是我们把这个留给你们去研究

通过这个小片段,我们可以编写适用于CORS XHR, XDR的代码,当它不起作用时,可以使用某种后备方法:

//检测浏览器对CORS的支持if ('withCredentials' in new XMLHttpRequest()){/*支持跨域请求*/ document. xmlwrite("支持CORS (XHR)");} else{if(typeof XDomainRequest !== "undefined"){//在XDR文档中使用特定于ie的"CORS"代码。write("支持CORS (XDR)");}else{//使用回退或填充文档撤退的时间。写(“没有CORS支持!”);}}

你可以在不同的浏览器中尝试此代码片段来证实它有效。

XMLHttpRequest2对象,其中包括所需的CORS支持,可用于CORS的功能检测浏览器支持。如果浏览器XHR对象具有XHR2“withCredentials”财产,你在做生意。如果没有,请执行步骤2。

在第2步中,我们再次尝试使用CORS,查找IE的专有版本XDomainRequest对象(使用相同的Access-Control-Allow-Origin顺便说一下,是头文件)。如果XDR对象存在,我们就在IE中,可以编写必要的代码来执行XDR CORS。

最后,如果所有这些都失败了(例如在旧版本的Opera或IE6/7中),我们必须提供另一种体验或为CORS找到一个hack。

处理Opera(或非cors浏览器)

假设我们达到了XHR2 /歌珥而且XDR都没有,下一步怎么办?放弃歌珥吗?事实证明,你有几个选择。您可以:

  1. 使用CORS填充材料有几个比较“俗气”的用于CORS的填料依赖于A)隐藏的Flash,或B)一些巫术HTML5。无论哪种方式,它们都绕过了浏览器限制,并试图为您提供一些表面上的CORS支持。

  2. 当然,如果您可以使用JSONP,那么对于所有浏览器,您都可以使用JSONP而不是CORS,因为它仍然受到更广泛的支持。但是,假设您试图“进化”过去的JSONP,除非您绝对需要它。在这种情况下,您可以使用Opera和旧浏览器退回到XHR和JSONP回调。

  3. 显示一个错误信息这是您最严厉的选择,但已给出大多数浏览器支持CORS,您可以简单地选择告诉一小部分用户更新他们的浏览器。这取决于Opera和IE 6/7流量对你的网站有多重要。

选择权在你,但显然,你有选择权一些这样的选择仍然会使CORS具有吸引力。

把它们放在一起

剑道UI提要阅读器演示,我们使用YQL将RSS XML直接提供给浏览器。YQL支持CORS,因此我们选择将XML而不是JSONP发送到浏览器来突出显示Kendo UI对XML的数据源支持

这个演示的版本1不支持非cors浏览器。为了增加对这些浏览器的支持,我们修改了代码,在IE中使用XDR,在Opera和所有非cors浏览器中使用YQL JSONP。

修复IE的jQuery $。ajax传输

使CORS代码与IE 8/9一起工作实际上非常容易一些代码写的德里克Kastner.使用jQuery 1.5+,您可以创建自定义传输实现来控制jQuery $.ajax的内部工作。德里克用XDR就做到了这一点。

他的iecors项目简单地在jQuery $中创建一个使用XDR的jQuery传输。Ajax在需要时请求。你所要做的就是把这个小的JS文件添加到你的页面,然后一切就开始工作了(不改变你的代码)。Kendo UI数据源,使用jQuery $。ajax在封面下,现在将在IE中使用XDR。

所以,为了让Feed Reader演示CORS在IE 8/9中工作,一个小片段被添加到页面底部,在jQuery之后,但在任何剑道脚本引用之前:

<!——[if lt IE 10]> < script src="scripts/ jQuery .iecors.js"> 

用更多代码和JSONP修复Opera

不幸的是,修复旧版本的Opera并不那么容易。最终,在Opera中没有干净的方法来做CORS。您可以选择为Opera (v12之前)用户显示“浏览器不支持”的消息,或者在CORS无法工作时咬紧牙关“退回”到YQL JSONP。

我们选择在Feed Reader演示中使用后一种方法,因为它还有助于扩展对其他旧浏览器的支持。

//**HACK for OPERA(和非xhr2 /XDR浏览器)//由于缺乏合理的OPERA工作方法来支持CORS,退一步使用//YQL支持JSONP时处理浏览器比不支持//CORS XHR或XDR如果(!('withCredentials' in new XMLHttpRequest()) && !(typeof XDomainRequest !== "undefined")){_feedItemDS = new kendo.data。DataSource({传输:{读取:{url: "#",数据类型:"jsonp"},方言:函数(选项){var result = ["callback=?","format=json"], data = options || {};返回result.join(“&”);}}, schema:{type:"json", data:"query.results.rss.channel. "Item ",}});//**END OPERA/非cors HACK}

现在,Opera(任何其他非cors浏览器)将使用指向JSONP端点的Kendo UI数据源的备用配置,并期待JSON响应。不是漂亮的代码,但它是功能性的。有时,这就是构建在每个主要浏览器和平台上运行的软件所需要的。

关于CORS的底线

希望这篇文章有助于强调CORS的价值,以及它如何与大多数现代浏览器一起使用。随着越来越多的应用程序代码转移到客户端,对CORS的需求只会增长。从今天开始使用它,帮助将web标准推向下一个水平。

另请参阅

在本文中
Baidu
map