适用于AJAX,CORS,Chrome和& HTTP错误代码(401,403,404,500)

时间:2012-10-01 09:43:53

标签: javascript google-chrome cors

背景

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

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

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

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

事实上,如果发生200,Chrome只会正常通过响应;吞下任何其他状态代码并中止AJAX调用。

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

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

  

当发生错误时,浏览器不能很好地报告出错的地方。   例如,Firefox报告所有错误的状态为0和空状态文本。   浏览器还会向控制台日志报告错误消息,   但是无法从JavaScript访问此消息。   处理错误时,您会知道发生了错误,但没有其他错误。

您可以使用chrome启动标记来禁用此安全性 - 只是为了测试后端是否正常运行,并且一个健全状态不会因丢失正确的状态代码而受到不适当的影响。见[2]

问题

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

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

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

我们的后端很好地写了相当,遵循当时认为具有成本效益的最佳实践;其中一个依赖于正确的HTTP状态代码。 我们反对的Java REST客户端运行良好。

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

问题

人们为解决这些问题做了什么? 有什么办法可以使CORS更适合可信的后端吗?

链接

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

3 个答案:

答案 0 :(得分:6)

刚遇到这个问题。设置401响应的HTTP头对我来说是个窍门。如果没有一些自定义,我正在使用的库没有正确地执行此操作。 e.g:

  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'

答案 1 :(得分:0)

我今天花了几个小时来寻找答案,同时在Chrome上开发了一个网络应用。 Some others已针对这种情况撰写了相当详细的分析。

存在两个潜在问题:

  1. 可能是Chrome正在进行预检,并且得到了非200或非CORS的响应

  2. 由于某种原因,我的非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服务的程序可能会执行相同的操作。希望这会有所帮助,并节省一些时间!

答案 2 :(得分:-2)

现在经过多次摆弄,我已经设法让它发挥作用。 腮红

似乎有很多伏都教构成了确保CORS在每个浏览器中都能正常工作的确切场景,但却追溯了许多问题:

  • 默认情况下,Nginx默认只在其反向代理中使用HTTP / 1.0
  • Tomcat默默地使用相同的密钥忽略重复的init-param声明,但是jetty将它们组合在一起(因此CORS过滤器在服务器中关闭但在开发者笔记本电脑中关闭),并且nginx覆盖了一些标头。

偶然发现了一个看起来完全禁止的东西,我最终编写了一个CORS 4xx-&gt; 200包装器作为jquery插件,试图解决这个问题。调试该插件使我最终得到修复。