如何防止 Chrome 将 AJAX 请求重定向到 HTTPS?

Posted

技术标签:

【中文标题】如何防止 Chrome 将 AJAX 请求重定向到 HTTPS?【英文标题】:How to prevent Chrome to redirecting AJAX requests to HTTPS? 【发布时间】:2014-10-09 04:14:29 【问题描述】:

我的 AngularJS 应用程序正在对我们的服务(由 Jetty 提供支持)执行许多 AJAX 请求。出于某种原因,仅某些用户会出现以下错误,并在被要求清除浏览器缓存时消失。这仅在 Google Chrome 上发生

我正在 www.domain.com 上尝试请求 api.domain.com。

XMLHttpRequest 无法加载 http://api.domain.com/my-service。这 请求被重定向到“https://api.domain.com/my-service”,其中 对于需要预检的跨域请求是不允许的。 /我的当前页面

请注意,Chrome 正在尝试将服务从 HTTP 重定向到 HTTPS。我的网站可以通过 HTTP 或 HTTPS 访问

这是 chrome://net-internals/#events 输出:

1523417: URL_REQUEST
http://api.domain.com/my-service
Start Time: 2014-08-15 14:17:39.809

t=5984 [st= 0] +REQUEST_ALIVE  [dt=26]
t=5984 [st= 0]   +URL_REQUEST_DELEGATE  [dt=0]
t=5984 [st= 0]      DELEGATE_INFO  [dt=0]
                    --> delegate_info = "extension AdBlock"
t=5984 [st= 0]      DELEGATE_INFO  [dt=0]
                    --> delegate_info = "extension AdBlock"
t=5984 [st= 0]   -URL_REQUEST_DELEGATE
t=5984 [st= 0]   +URL_REQUEST_START_JOB  [dt=26]
                  --> load_flags = 143540480 (DO_NOT_SAVE_COOKIES | DO_NOT_SEND_AUTH_DATA | DO_NOT_SEND_COOKIES | ENABLE_LOAD_TIMING | MAYBE_USER_GESTURE | REPORT_RAW_HEADERS | VERIFY_EV_CERT)
                  --> method = "OPTIONS"
                  --> priority = "LOW"
                  --> url = "http://api.domain.com/my-service"
t=5984 [st= 0]      URL_REQUEST_REDIRECT_JOB
                    --> reason = "HSTS"
t=5985 [st= 1]     +URL_REQUEST_DELEGATE  [dt=25]
t=5985 [st= 1]        DELEGATE_INFO  [dt=25]
                      --> delegate_info = "AsyncResourceHandler"
t=6010 [st=26]     -URL_REQUEST_DELEGATE
t=6010 [st=26]      CANCELLED
t=6010 [st=26]   -URL_REQUEST_START_JOB
                  --> net_error = -3 (ERR_ABORTED)
t=6010 [st=26]    URL_REQUEST_DELEGATE  [dt=0]
t=6010 [st=26] -REQUEST_ALIVE

知道为什么 Chrome 会强制进行这样的重定向吗?我在网络选项卡中看不到任何错误,该请求没有返回任何内容。

更多信息:

这是正常运行的 Chrome 浏览器上的响应标头。

Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:X-Requested-With, authorization, content-type, X-CSRF-Token
Access-Control-Allow-Methods:GET, POST, HEAD, PUT, OPTIONS
Access-Control-Allow-Origin:http://api.domain.com
Content-Length:0
Server:Jetty(8.y.z-SNAPSHOT)

【问题讨论】:

【参考方案1】:

这可能是由无处不在的 HTTPS 等扩展或严格传输安全 (HSTS) 引起的。

这些因素不在您的控制范围内,要解决它,您需要修改服务器端 API 端点以提供 CORS 响应标头,例如:

Access-Control-Allow-Origin: http://api.domain.com

... 或者只是在侧面强制执行 https。那么你就不用担心 http/https 来源违规了。作为奖励,https 最近已成为您网站在 Google 上排名的积极因素之一。


问题中的日志清楚地表明,HSTS 是罪魁祸首。 Chrome 的 HSTS 实现目前无法正常处理跨域请求 (crbug.com/387198)。网站所有者解决此错误的唯一方法是强制执行横向 https,并通过 https 访问 API。

如果您想重现该错误,请访问chrome://net-internals/#hsts 并通过第一个输入框(“添加域”)将域添加到 HSTS 列表中。然后,在重现错误后,通过第二个输入框(“删除域”)从 HSTS 列表中删除域。此方法也是用户解决该错误的一种方法。毕竟,如果该域从 HSTS 列表中删除,则不再有 HSTS 重定向。

什么是 HSTS? 服务器在其任何 https 响应中发送 Strict-Transport-Security 标头后激活 HSTS。浏览器收到这个header一次后,会强制网页上的所有资源都通过https请求。有关详细信息,请参阅 http://chromium.org/sts 和 http://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security。

由于此错误仅发生在您的某些用户中,因此很可能是由浏览器扩展或 API 域中的某些页面引起的,该页面以 STS 标头进行响应。

【讨论】:

它可以在我的机器上运行,但不能在我同事的 Chrome 上运行,我已经编辑了问题以在它运行时显示来自服务器的响应。 更好的评论:它可以在我的机器上运行,但不能在我同事的 Chrome 上运行(但他可以以标准 HTTP 模式浏览​​网站),我已经编辑了问题以显示服务器的响应作品。谢谢,我会考虑迁移到全 HTTPS 网站。 @vincentp 您问题中的日志清楚地表明,HSTS 是罪魁祸首。 Chrome 的 HSTS 实现目前不能正确支持 CORS。我已在 7 周前向 Chromium 提交了针对该错误的补丁,但该补丁仍在审核中:codereview.chromium.org/348253002。在该补丁被接受之前,您不能将 CORS 与 HSTS 结合使用。 非常感谢您的帮助。我以前从未听说过 HSTS。我试图了解事件链并理解为什么 Chrome 会认为这个域/查询应该通过 HTTPS 完成。这是在 Web 服务器级别为域定义的吗?我们有一个由 nginx 运行的负载均衡器,它负责处理 SSL 证书和其他事情,它可以在这里吗? 再次感谢,我会深入研究我们的配置。

以上是关于如何防止 Chrome 将 AJAX 请求重定向到 HTTPS?的主要内容,如果未能解决你的问题,请参考以下文章

如何将从 Ajax 请求收到的响应重定向到另一个 html 页面

使用 jQuery 和 AJAX 提交表单如果 return 设置为 false 则不会将值插入 SQL 以防止重定向

当发送的请求是 Ajax 请求时,如何从 ManagedBean 重定向?

301重定向后如何防止chrome从磁盘缓存中加载index.html

停用的用户重定向到从 ajax 请求登录

Chrome 在重定向时取消 CORS XHR