AJAX、CORS、Chrome 和 HTTP 错误代码 (401,403,404,500) 的推荐解决方案

Posted

技术标签:

【中文标题】AJAX、CORS、Chrome 和 HTTP 错误代码 (401,403,404,500) 的推荐解决方案【英文标题】:Recommended solution for AJAX, CORS, Chrome & HTTP error codes (401,403,404,500) 【发布时间】:2012-09-22 03:49:08 【问题描述】:

背景

(如果你熟悉 CORS,可以跳到最后的问题

CORS [1] 是一种允许浏览器允许访问来自不同域的资源的解决方案。例如。使用 AJAX 的 REST 数据后端。

在 Internet 上很好地观察到,当此类资源需要时,Chrome(和 Webkit 朋友)不会处理 HTTP 身份验证提示。例如。 [2] (这是为了防止浏览器显示身份验证登录对话框,例如,当图像标签加载失败并出现 401 并需要凭据时,Web-Mail 登录页面。用户可能会被骗输入他们的 webmail 凭据)

Chrome 在这种情况下的行为是放弃响应,几乎默默地取消请求。

实际上,Chrome 只会在出现 200 时才会让响应正常通过;任何其他状态码都被吞下,AJAX 调用被中止。

如果使用 jQuery 执行 Ajax 请求,并且远程站点以 HTTP 401 状态代码响应,则请求被取消并且 ajax 完成并出现错误,但缺少 401 代码。就好像连接死了或等效的低层问题。

我见过的唯一一个特别提到 CORS 警告的网站是 [1]

当出现错误时,浏览器不会很好地报告问题所在。 例如,Firefox 报告所有错误的状态为 0 和空的 statusText。 浏览器还会向控制台日志报告错误消息, 但无法从 javascript 访问此消息。 在处理 onerror 时,您会知道发生了错误,但其他的不多。

您可以通过使用 chrome 启动标志来禁用此安全性 - 只是为了测试后端是否“正常”运行,并且一个理智没有因丢失正确的状态代码而受到过度影响。见[2]

问题

如果后端和前端客户端代码应该使用 401 作为其身份验证过程的一部分怎么办? - 任何失败都只是被分解为一个“错误”输出。

例如:发出身份验证请求时 - 例如2-legged OAuth 令牌请求 - 针对 RESTful 后端 - 使用正确的状态代码 - 客户端不知道是否:

401 用户未通过身份验证。 ---连接失败。 400 有一个错误的请求。 500 服务器有问题。 207成功后没有内容。

我们的后端相当以 REST 方式编写,遵循当时被认为具有成本效益的尽可能多的最佳实践;其中之一是依赖正确的 HTTP 状态代码。 我们使用的 Java REST 客户端运行良好。

现在我已经开始创建一个 Javascript 客户端,用于嵌入网页 - 特别是使用 CORS,我们在 Chrome 等中遇到了问题。(注意 Firefox 似乎很好,我们通常不会目前关心IE。)

问题

人们为解决这些问题做了哪些工作? 有什么办法可以让 CORS 更适合受信任的后端?

链接

    CORS 教程:http://www.html5rocks.com/en/tutorials/cors/ Chrome 不允许 401 触发的资源身份验证提示:http://code.google.com/p/chromium/issues/detail?id=81251 --禁用 Chrome 的网络安全性:Disable same origin policy in Chrome

【问题讨论】:

【参考方案1】:

刚刚遇到这个问题。为 401 响应设置 HTTP 标头对我有用。如果没有一些定制,我正在使用的库无法正确执行此操作。例如:

  self.headers["Access-Control-Max-Age"] = '1728000'
  self.headers["Access-Control-Allow-Origin"] = "http://localhost:3001"
  self.headers["Access-Control-Allow-Methods"] = "ANY"
  self.headers["Access-Control-Allow-Credentials"] = 'true'

【讨论】:

【参考方案2】:

我今天花了几个小时寻找这个问题的答案,同时在 Chrome 上开发一个网络应用程序。 Some others 已经对这种情况进行了相当详细的分析。

有两个潜在问题:

    可能是 Chrome 正在执行预检并得到一个非 200 或非 CORS 响应作为响应

    Specs about Preflights (When they Occur)

    由于某种原因,我的非 200(错误)状态代码没有附加标题。 正如我在this post 中发现的那样,第二个原因就是问题所在。本质上,nginx 默认只在成功响应上添加标头。为了通过 CORS 获得我的错误响应,改变就足够了

add_header 'Access-Control-Allow-Origin' '*';

add_header 'Access-Control-Allow-Origin' '*' always;

如文章所述,您可能还需要将always 添加到'Access-Control-Allow-Credentials''Access-Control-Allow-Headers'。这样做之后,所有错误代码也都通过了,没有 CORS 问题。 您用于 API 服务的程序可能也是如此。希望这可以帮助并节省一些时间!

【讨论】:

【参考方案3】:

现在经过大量的摆弄,我已经设法让它工作了。 脸红

似乎有非常多的巫术构成了确保 CORS 可以在每个浏览器中工作的确切场景,但是已经追溯了许多问题,例如:

Nginx 默认只在其反向代理中使用 HTTP/1.0 Tomcat 会默默地忽略具有相同密钥的重复 init-param 声明,但 jetty 将它们组合在一起(因此 CORS 过滤器在服务器中关闭,但在 dev-laptop 中打开),并且 nginx 覆盖了一些标头。

偶然发现似乎完全不行,我最终编写了一个 CORS 4xx->200 包装器作为 jquery 插件,试图解决这个问题。调试该插件导致我最终修复。

【讨论】:

但是 500 仍然被丢弃,并且没有返回给调用 javascript 代码。 最终解决了什么问题? 很好的问题,但不好的答案。请提供最终解决方案是什么

以上是关于AJAX、CORS、Chrome 和 HTTP 错误代码 (401,403,404,500) 的推荐解决方案的主要内容,如果未能解决你的问题,请参考以下文章

ajax——CORS跨域调用REST API 的常见问题以及前后端的设置

为啥 Chrome 和 Firefox 使用基本身份验证的 CORS ajax 调用的行为不同?

带有 jQ​​uery.ajax() 的 CORS

在 Apache 中启用了 CORS,但 AJAX 不起作用(chrome 表示不允许来源)

Chrome 在重定向时取消 CORS XHR

jQuery Ajax cors IE10 不工作