5

假设我控制两个域,www.api_domain.com并且www.website_domain.com. www.api_domain.com提供一个 API,要求用户进行身份验证,然后使用会话 cookie 来识别发出请求的用户。www.website_domain.com将脚本加载到其页面上,www.api_domain.com并且该脚本希望www.api_domain.com使用当前用户的 cookie 调用 API URL,并以某种方式在页面上使用结果www.website_domain.com

对于最初加载脚本,或任何不需要用户会话 cookie 工作的 API URL,最简单的解决方案就是使用

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

来自 的响应的标头www.api_domain.com。这似乎在除 IE 之外的所有浏览器上都可以开箱即用,尽管 IE 不会尊重使用 jQuery 的 AJAX 方法发出的 AJAX 请求的 Allow-Origin 标头,但有像 xdr.js 这样的库在幕后做了一些魔术使 jQuery、IE 和 Allow-Origin 标头可以很好地协同工作,并且在所有其他浏览器中都表现得像(我不知道 xdr.js 所做的细节,但据我所知,它非常适用于非凭据请求)。

当我想点击http://www.api_domain.com需要用户会话 cookie 的 URL 时,问题就来了。当在与浏览器无关的环境中讨论此问题时,通常会提出两种解决方案:

  1. 使用Access-Control-Allow-Credentials: true来自的响应,即使跨域请求也可以发送 cookie。
  2. http://www.website_domain.com在带有 origin 的页面上创建一个 iframe ,让两个窗口使用HTML5 发布消息http://www.api_domain.com相互通信,并将发出请求的所有责任委托给 iframe。http://www.api_domain.com

如果可能的话,我更喜欢使用选项 1,因为它可以让你编写 Javascript 代码来使用 API,http://www.api_domain.com就像你编写它来接触同域 API 一样。要使用 iframe 方法,我们需要学习或创建一些框架,用于向 iframe 发送类似 AJAX 的请求,以及成功和错误处理程序。这也意味着我们需要创建要加载到 iframe 中的代码,这将只是一整块用于访问 API URL 的瘦包装器。它看起来比第一种方法更丑陋、更棘手、更难理解。

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

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

4

2 回答 2

9

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

这是前微软开发人员 Eric Law 的一篇文章,详细讨论了这个问题:http: //blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-变通办法.aspx

相关部分明确说明在 IE 8 和 9 中无法通过 CORS 请求发送 cookie,具体如下:

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

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

...

5:请求中不会发送身份验证或 cookie

为了防止滥用用户的环境权限(例如 cookie、HTTP 凭据、客户端证书等),请求将被剥离 cookie 和凭据,并且将忽略 HTTP 响应中的任何身份验证挑战或 Set-Cookie 指令。XDomainRequests 将不会在先前经过身份验证的连接上发送,因为某些 Windows 身份验证协议(例如 NTLM/Kerberos)是基于每个连接而不是基于每个请求的。

希望对跨域请求执行用户身份验证的站点可以使用显式方法(例如 POST 正文或 URL 中的令牌)来传递此身份验证信息,而不会危及用户的周围权限。

现在假设您控制这两个位置,您大概可以创建一个服务器到服务器的身份验证过程,并为另一个域传递从域提供的各种会话 ID,客户端实际上是通过您的请求打开的。它不漂亮,但它有效。文章中也提到了这种方法。不过,您需要小心,因为它打开了会话劫持的可能性。

于 2013-03-10T09:13:15.430 回答
0

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

jQuery 插件,它在浏览器(包括 IE8+)之间透明地添加跨域资源共享 (CORS),以允许带有 cookie 和标头支持的跨域 Ajax 请求。

我也认为但不确定 IE 不支持在标头中使用通配符,例如Access-Control-Allow-Origin: *.

于 2013-03-09T22:10:42.693 回答