2013-03-01 86 views
5

假设我控制两个域,即www.api_domain.comwww.website_domain.comwww.api_domain.com提供了一个API,要求用户进行身份验证,然后使用会话Cookie来识别发出请求的用户。 www.website_domain.comwww.api_domain.com将脚本加载到其页面上,并且该脚本想用当前用户的cookie拨打www.api_domain.com上的API URL并在www.website_domain.com的页面上以某种方式使用结果。没有iframe的IE 8和9的跨域cookie?

;初始加载脚本,或者不需要用户的会话cookie来工作的任何API网址,最简单的方法是简单地从www.api_domain.com响应使用

Access-Control-Allow-Origin: http://www.website_domain.com 

头。这似乎在除了IE之外的所有浏览器中都可以使用,尽管IE不会遵守使用jQuery的AJAX方法进行的AJAX请求中的Allow-Origin头部,但有些类似于xdr.js的库在后台执行一些魔术,使jQuery,IE和Allow-Origin头文件在一起很好地运行,并且在所有其他浏览器中表现得很像(我不知道xdr.js的具体细节,但是对于非凭证请求我可以很好地工作)。

问题出现在我想要访问需要用户会话cookie的http://www.api_domain.com上的URL。当这个问题在浏览器无关的设置进行了讨论,两种解决方案通常建议:

  1. 从 响应使用Access-Control-Allow-Credentials: true做饼干甚至跨域请求被发送。
  2. http://www.website_domain.com原产 http://www.api_domain.com在页面上创建一个iframe,有两个窗口使用HTML5 post messages与 相互通信,并委派发出请求http://www.api_domain.com到 iframe的所有 责任。

我会非常喜欢,如果可以使用选项1,因为它可以让你写你的JavaScript代码,你会写这倒好同域的API相同的方式使用API​​上http://www.api_domain.com。要使用iframe方法,我们需要学习或创建一些框架,用于向iframe发送类似AJAX的请求,并带有成功和错误处理程序。这也意味着我们需要创建要加载到iframe中的代码,这只是用于访问API URL的整个精简包装器。它看起来比第一种方法更丑陋,更棘手,更难理解。

但是,我不知道如何使选项1工作在IE浏览器。我在我的API网址上设置了Access-Control-Allow-Credentials: true,所有其他浏览器都向这些网址发送了cookie,但即使使用xdr.js库,IE 9也不会。 (我还没有在IE 8上测试过)。没有任何其他症状可以报告。当我在IE的开发人员工具中查看它们时,我可以在www.api_domain.com的响应中看到正确的Access-Control-Allow-OriginAccess-Control-Allow-Credentials标题,但请求中没有cookie标头。

是否存在一些黑客或魔法咒语,我可以使Internet Explorer尊重Access-Control-Allow-Credentials标题,或者我可以使用IE的其他标题识别?

+1

设置p3p隐私策略有帮助吗? http://stackoverflow.com/questions/2666376/copying-cookies-cross-domain-why-is-ie-blocking-cookies-other-browsers-are-send?rq=1 – flup 2013-03-08 20:44:19

+0

@flup Nope,这是完全不相干的这个。 – 2014-04-20 11:15:31

+0

另一方面,这无助于回答这个问题,但可能对任何读者都有用:而不是制作自己的代理iframe,考虑使用[this library](https://github.com/jpillora/xdomain/) 。我没有对它进行测试,但它看起来应该透明地完成通过邮件为您提供代理跨域AJAX流量的所有工作。除非您另外需要supercookie支持来处理越来越多的默认情况下阻止“第三方”cookie的浏览器(包括在iframe中设置的cookie),它应该是足够的。 – 2014-04-20 11:28:23

回答

9

选项1在IE9或更低版本中是不可能的,因为不支持使用XMLHttpRequest的CORS。此外,如果您尝试使用XDomainRequest,则您将永远无法随您的请求一起发送任何Cookie。我多次在这个道路上努力编写一个用于测试用例的ui测试库。你想要做的只是不可能以这种方式。

这里是一个后由Eric法,一名前微软开发者,在详细讨论这个问题: http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx

的有关章节,这清楚地表明了CORS请求发送的cookie中IE 8是不可能的, 9,如下所示:

在Internet Explorer 8中引入了XDomainRequest对象。此对象允许AJAX应用程序直接创建安全的跨源请求,方法是确保只有当数据源指示响应为公共时,才能通过当前页面读取HTTP响应;这样,同源策略安全保证就受到保护。响应表明他们愿意通过包含具有值*的访问控制 - 允许源HTTP响应标头或调用页面的确切来源来允许跨域访问。

在设计新对象时,确保现有网站和服务不会受到威胁是我们的首要任务。为此,我们对可以使用XDomainRequest对象进行哪些请求施加了许多限制。

...

5:未认证或Cookie将与请求

发送为了防止用户的周围滥用权力(如饼干,HTTP的凭证,客户端证书等),该请求将被删除Cookie和凭据,并且将忽略HTTP响应中的任何认证挑战或Set-Cookie指令。由于某些Windows身份验证协议(例如NTLM/Kerberos)是基于每个连接而不是基于每个请求的,因此XDomainRequests不会在先前通过身份验证的连接上发送。

希望对用户进行跨源请求认证的站点可以使用显式方法(例如POST主体或URL中的令牌)传递此认证信息而不会冒用户的环境权限。

现在假设您可以控制的位置,你大概可以创建一个服务器到服务器的认证过程,并着手通过从域提供各种各样的会话ID,对于其他领域,其中的客户实际上是在通过你的申请。这并不漂亮,但它的工作原理。文章中也提到了这种方法。你会想要小心,因为它会打开会话劫持的可能性。

+0

真棒链接,谢谢。清楚表明这是不可能的。服务器到服务器认证似乎比使用iframe更加笨拙的解决方案,所以我现在坚持使用iframe解决方案。 – 2013-03-10 16:01:36

0

IE8 +有XMLHttpRequest的替代方案,它支持的凭据是XDomainRequest。无论如何,XDomainRequest不是由JQuery实现的,因为它的功能比XMLHttpRequest提供的功能少,但是有像jQuery CORS Plugin这样的插件可以提供您需要的功能。

jQuery插件,透明地增加了跨源资源共享 (CORS)之间的浏览器包括IE8 +,允许跨域Ajax请求 与cookies和头部的支持。

我也想到但不确定IE不支持Access-Control-Allow-Origin: *等标头中的通配符。

+0

我们不使用通配符;根据CORS规范,您无法在任何浏览器中使用具有凭证请求的通配符。您链接到的github回购看起来很有前途,但我有点困惑。那里有Java和Javascript,没有使用说明;是这样的想法,即Javascript只能与Java服务器一起使用,以某种方式处理请求? – 2013-03-10 00:12:01

+0

其实我还没有尝试过,我认为java只是用于服务器端测试。你也可以检查这个https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest – 2013-03-10 00:25:05