由于 Chrome 中缺少预检请求而被阻止的 HTTP 重定向

Posted

技术标签:

【中文标题】由于 Chrome 中缺少预检请求而被阻止的 HTTP 重定向【英文标题】:Blocked HTTP redirect due to missing preflight request in Chrome 【发布时间】:2017-08-25 11:20:58 【问题描述】:

我们目前正在构建一个支持 RESTful API 的 Angular 应用程序。该应用程序尝试使用以下请求 URL 获取用户信息:http://example.com:1337/api/users/1。此资源以 HTTP 301(永久移动)响应并设置资源已移动到的位置标头,例如Location=http://another-hostname.com:8088/new/users/1。 Angular 的 HTTP 客户端或者浏览器会自动处理这个响应并重定向到这个新位置。

遗憾的是,在 Chrome 中我们收到以下错误消息:

XMLHttpRequest cannot load http://example.com:1337/api/users/1. Redirect from 'http://example.com:1337/api/users/1' to 'http://another-hostname.com:8088/new/users/1' has been blocked by CORS policy: Request requires preflight, which is disallowed to follow cross-origin redirect.

Chrome 在调用 GET 到新资源之前会跳过预检请求 (CORS)。我们用 Firefox 对此进行了测试,它运行良好。 Firefox 发出新的预检请求,之后的 GET 请求将被成功处理。

所以,我想知道这里的正确行为是什么。有没有人有过 30 倍响应的类似经历?

是否有可能禁用自动浏览器(或 Angular HTTP 客户端)重定向处理?这样我们就可以使用全新的this.http.get(...) 手动处理新的 GET。

感谢您的建议,

迈克尔

【问题讨论】:

您是否尝试过创建自定义 XHRBackend 服务来处理 HTTP 30X 重定向?我只是不确定它是否在 30X 响应时被调用,但如果是,你可以在那里解决问题。 【参考方案1】:

Chrome 在调用 GET 到新资源之前会跳过预检请求 (CORS)。我们用 Firefox 对此进行了测试,并且运行良好。 Firefox 发出新的预检请求,之后的 GET 请求将被成功处理。

您可以在此处找到有关此问题的讨论以及其他解决方法以及指向 W3C CORS 建议的相应部分的链接:https://***.com/a/39728229/4282127。

Chrome 自 57 版起应支持重定向 (3xx) 时的预检请求。因此,更新到最新的 Chrome 版本应该至少可以解决丢失预检请求的问题。

【讨论】:

我已经更新了我的浏览器...... Chrome 57 确实根据最新的 CORS 规范处理了重定向的预检请求。【参考方案2】:

是否有可能禁用自动浏览器(或 Angular HTTP 客户端)重定向处理?

XMLHttpRequest(以及 Angular 的 $http 因此)没有办法。 fetch() 中提供了这样的选项,它还不是跨浏览器。

但是有一个解决方法:

    通过特殊的初步确定最终请求目的地 请求(通过检查 XHR.responseURL)。这应该是一个简单请求:只有 GET/POST/HEAD 并且只有 simple headers — 这样它就不会产生预检.

    向该目的地提出“真实”请求。


这里的正确行为是什么

跨站重定向最初是被禁止的,但现在 (since 4 Aug 2016) 是允许的——但大多数浏览器还没有实现这一变化。

这在MDN https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests_and_redirects中有非常清楚的解释

【讨论】:

以上是关于由于 Chrome 中缺少预检请求而被阻止的 HTTP 重定向的主要内容,如果未能解决你的问题,请参考以下文章

从源 xxxx 访问 XMLHttpRequest ' 被 CORS 策略阻止:对预检的响应。预检请求不允许重定向

跨域请求被阻止原因:CORS 预检通道未成功

过滤掉 chrome 开发工具中的预检/选项请求

Chrome中的慢速cors预检选项请求[关闭]

来源已被 CORS 策略阻止 对预检请求的响应未通过访问控制检查

为啥经过身份验证的 CORS 请求的预检 OPTIONS 请求在 Chrome 中有效,但在 Firefox 中无效?