CORS,在 Chrome v36 中工作,在 Chrome v37 中失败

Posted

技术标签:

【中文标题】CORS,在 Chrome v36 中工作,在 Chrome v37 中失败【英文标题】:CORS, working in Chrome v36, failing in Chrome v37 【发布时间】:2014-11-04 02:56:14 【问题描述】:

当我从 Chrome v36.xxx 更新到 v37.yyy(特别是 37.0.2062.103)时,我花了几天时间试图确定为什么我的 CORS 应用程序突然开始在 Chrome 中失败。在我的应用程序中,我运行一个 MVC 站点和一个不同端口上的 WebAPI。这就是跨域出现的地方。

我有几个实例(dev、uat、prod)都以相同的方式运行。都过去了。

XMLHttpRequest 无法加载 http://"mywebapihost":"mywebapiport"/api/v1.0/myapp/。不 请求中存在“Access-Control-Allow-Origin”标头 资源。因此不允许访问 Origin 'http://"mymvchost"'。

似乎是 Preflight 中的 OPTIONS 请求存在问题 - 我在网上看到很多提及。

但是 - 我觉得离“修复”我的问题没有任何距离(“修复”== 能够在 Chrome 中运行)。

关于我的系统我可以说明的事情:

(1) 一直使用 v36.xxx,但自从 37.0.2062.103 更新后就没有了 (2) 在 IE 中工作 (3) 即使在最新的 Chrome 中也适用于 GET (4) 工作,即使在最新的 Chrome 中。如果我有 Fiddler 正在运行(我不认为这是一个修复!)

我已经尝试过了。

1) 在调用 jQuery Ajax 调用中强制标头尝试将授权获取到 OPTIONS 调用中 - 来自网络的建议

beforeSend: function (xhr) 
   xhr.setRequestHeader('Authorization', make_base_auth("<username>", "<password>"));
,
headers: 
   "Authorization": "Basic " + btoa("<username>" + ":" + "<password>")

2) 我下载了 Chrome Canary v39.0.2150.3,希望这个问题会消失 - 仍然会遇到同样的故障。

如果有人有任何建议,我将非常感激,我必须更改为运行 IE 才能取得进步!

【问题讨论】:

报告的 Origin 显然是错误的。你是在本地机器上运行这个测试吗? 已编辑。我会为 mvc 主机、webapi 主机和 webapi 端口放入占位符,但是因为我将它们放在“”中,所以它们没有出现在帖子中。顺便说一句 - mvc 主机和 web api 主机是相同的。只有端口不同,显然仍属于“跨域”。 你能调试服务器看看为什么它没有附加 Access-Control-Allow-Origin 标头吗? @Ryven:我确实拥有对服务器的完全访问权限,是的。这是在 IIS 上运行的(从历史上看,我更像是一个 Java/Tomcat 人),但我确实可以访问所有配置和日志文件。事情是,如果我使用诸如“Postman”(Chrome 插件)之类的工具发出明确的 OPTIONS 请求,它确实可以通过。失败的事情,我现在看到它不仅是 Chrome,还有 Firefox,是使用 jQuery Ajax() 为 POST 或 PATCH 请求自动生成的 OPTIONS Preflight。我认为它只是通过 Chrome 出现,因为更新使其更加严格。 【参考方案1】:

为了结束,我在这里回答我自己的问题。将来可能会对某人有所帮助。

我所做的是创建一个完全干净、最小工作的 WebAPI 项目,它实现了 GET、PUT、POST 和 DELETE。我按预期工作,然后尝试跨域(同一台服务器,但运行 JS Ajax 的网页在端口 80 上,WebAPI 在端口 7694 上运行)。

这出乎意料地失败了。然后我用所需的 nuget 包启用了 CORS,添加了

        config.EnableCors();

在 WebApiConfigcs 中。

在我的最小 WebAPI 控制器中,我添加了

[EnableCors(origins: "*", headers: "*", methods: "*", SupportsCredentials = true)]

所有这些都按预期工作。

但是,当我随后将相同的控制器等安装到我现有的失败的 WebAPI 部署中时,它以提示我最初问题的方式失败了。

所以它有配置的味道。

结果是通过清理我的 IIS 服务器和我正在部署的 WebAPI 项目的配置来解决的。在尝试使飞行前 OPTIONS 请求起作用时,我对两者都进行了太多的探索。

具体来说,我在 Web.Config 中添加了

  <system.web>
    ....
    ....
    <!--<authentication mode="Windows" />-->
    <authorization>
      <deny users="?" />
      <allow verbs="OPTIONS" users="?" />
    </authorization>
  </system.web>

还有

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE" />
    <add name="Access-Control-Allow-Headers" value="Content-Type" />
  </customHeaders>
</httpProtocol>

当遵循网上看到的建议时。

我删除了这两个,事情开始起作用了。

我很欣赏这是一个有点模糊的答案,但它可能会减轻我几天来的挫败感。

克里斯

【讨论】:

【参考方案2】:

我也有同样的问题。我刚刚更新到 Chrome 38 (38.0.2125.101 m) 并且问题仍然存在。如下所示,我在这里删除了我的答案并创建了一个新问题:Chrome v37/38 CORS failing (again) with 401 for OPTIONS pre-flight requests。

正如您将在该问题中看到的那样,我的 Angular 应用正在发送明确的 withCredentials,因此服务器应该正确验证预飞行的 OPTIONS 请求。

【讨论】:

您的请求缺少Authorization 请求标头。你设置xhr.withCredentials = true了吗?您能否删除此“答案”并发布一个新问题,其中包含 OPTIONS 请求的请求标头和响应标头以及最终响应? Rob,请看我新添加的问题(上面的链接)

以上是关于CORS,在 Chrome v36 中工作,在 Chrome v37 中失败的主要内容,如果未能解决你的问题,请参考以下文章

Rest api在chrome中返回“网络连接失败”,但在firefox中工作正常

cors 不能在具有 express 的 firebase 功能中工作

protractor - 启动 chrome 以禁用 cors 的网络安全

CORS 无法在没有 SSL 证书的 IIS 服务器中工作

[Ctrl + C在浏览器为Google Chrome时无法在Flash Player(swf文件)中工作]] << [

CORS无法在php slim框架中工作