在带有 Node 和 Express 的 IE10 中使用 CORS 的安全错误

Posted

技术标签:

【中文标题】在带有 Node 和 Express 的 IE10 中使用 CORS 的安全错误【英文标题】:Security error using CORS in IE10 with Node and Express 【发布时间】:2013-08-27 16:40:06 【问题描述】:

我正在构建一个托管在 http://example.com 上的 Backbone 应用程序,它利用托管在 https://api.example.com 上的 API。对于 API,我将 Node.js 与 Express.js 框架一起使用。我的 CORS 解决方案似乎适用于除 IE 之外的所有主流浏览器(它甚至在 IE10 中失败)。

从 IE10 发起请求时,该请求永远不会到达 API 服务器。据我所知,甚至没有发送请求。当我使用 IE10 的开发人员工具检查请求时,请求标头和响应标头都是空白的。当从任何其他浏览器发送请求时,会收到请求并正确生成响应。

这是我在控制台看到的错误:

SCRIPT 7002: XMLHttpRequest: Network Error 0x4c7, The operation was canceled by the user.

请求使用jQuery:

$.ajax(
  url: apiRoot + "/endpoint",
  success: function(response) 
    // Omitted irrelevant code
  
);

根据this的文章,CORS在IE中默认是关闭的,必须开启:

Internet Explorer 默认忽略 Access-Control-Allow 标头 禁止 Internet Zone 的跨域访问。要启用 CORS,请转到 工具->Internet 选项->安全选项卡,单击“自定义级别”按钮。 找到杂项 -> 跨域访问数据源设置 并选择“启用”选项。

果然,当我启用此设置时,请求通过并且一切正常。但是,我读到此设置实际上与 CORS 无关,不应该影响它。当使用this tool 测试 CORS 兼容性时,无论此设置是启用还是禁用,IE10 都会通过,这让我相信 CORS 已启用,而我只是做错了。

此外,当我运行 Fiddler 时,一切似乎都正常运行,因为 Fiddler 充当代理。

供参考,这里是服务器端的CORS相关代码:

res.header("Access-Control-Allow-Origin", "example.com");
res.header("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS");
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-File-Name, X-File-Size, X-File-Type");
res.header("Access-Control-Allow-Credentials", true);
if (req.method == "OPTIONS") 
 res.send(200);

【问题讨论】:

首先,对于任何有凭证的跨域请求,Access-Control-Allow-Origin 标头中不允许使用通配符。这可能不是您的问题,但这可能会在以后给您带来麻烦。如果您不打算支持凭据 CORS,请从响应中删除 Access-Control-Allow-Credentials 标头。如果您确实想支持凭据 CORS,则必须在 Access-Control-Allow-Origin 响应标头中定位特定域。 @RayNicholus:感谢您的评论。我一直在尝试我能想到的一切——我最初在那里有一个特定的域,但显然通配符是我在写这个问题之前尝试的最后一件事。 请根据 IE10 共享相关请求的标头以及响应标头。这可能会提供更多有用的证据。 没有要检查的标题。该请求甚至在发送之前就被 IE 阻止了。 那么这不是 CORS 问题。 【参考方案1】:

尝试使用 HTTP 而不是 HTTPS 将请求发送到 API 服务器。这个问题听起来可能与服务器的 SSL 设置有关,而不是与请求本身有关。如果是这种情况,请尝试使用 SSL 设置。

var options = 
  key:    fs.readFileSync(key),
  cert:   fs.readFileSync(certificate),
  ca:     fs.readFileSync(CA),
  requestCert:        false,
;

https.createServer(options, app).listen(443);

【讨论】:

【参考方案2】:

我遇到了同样的问题,最后为了让事情更容易我做了一个 nginx proxy_pass 指令 所以我让http://example.com/api 指向http://api.example.com 然后在 javascript 代码中将请求 example.com/api 并且浏览器不会抱怨。

我知道这并不理想,但并非所有浏览器都以相同的方式支持 CORS,尤其是 IE。 当您想支持所有浏览器时,proxy_pass 选项是最简单的方法。

在其他情况下,您将进行更改以使事情在 IE 中运行并破坏其他浏览器的支持。 不是说不可能,而是需要更多的考验。

【讨论】:

感谢您的回答!我没想过使用proxy_pass。如果一切都失败了,那么我可能会走这条路。但是,IE10 中的 CORS应该 以与其他现代浏览器相同的方式工作 - 我不禁认为我做错了什么...... @DavidJones 我知道这已经有一段时间了,但你有没有找到解决方案?我正在努力解决 IE10 的类似问题。【参考方案3】:

为了让我的 CORS 请求在 IE 中工作,我必须像这样拨打电话:

$.ajax(
  url: apiRoot + "/endpoint",
  xhrFields: 
     withCredentials: true
  ,
  crossDomain: true,
  success: function(response) 
    // Omitted irrelevant code
  
);

【讨论】:

以上是关于在带有 Node 和 Express 的 IE10 中使用 CORS 的安全错误的主要内容,如果未能解决你的问题,请参考以下文章

Mac 上带有 Node 和 Express 的 Docker 容器,未在浏览器中显示?

静态文件,带有 Node.js 和 Express 的样式表

带有 Express 异步 API 调用的 Node.JS

带有 Express 框架的 Node.js 中的自定义事件

带有 HTTP-AUTH 的 node.js Express

如何使用 Node、Express、Axios 在 ReactJS 前端设置带有 JWT 令牌的 cookie