【问题标题】:CORS request with Preflight and redirect: disallowed. Workarounds?带有 Preflight 和重定向的 CORS 请求:不允许。解决方法?
【发布时间】:2016-04-29 05:13:37
【问题描述】:

我正在设计一个 API,它允许用户进行身份验证(使用令牌)并包含同一域内的重定向。现在,对于返回 303 的端点的未经身份验证的请求,

GET /documents/123  --> 303 redirect to `/documents/abc`
GET /documents/abc  --> 200

一切都很顺利。

让我们向发送Authorization 标头的同一端点发出经过身份验证的请求。这使得请求成为 preflighted request 并且浏览器执行预检 OPTIONS 请求,即

OPTIONS /documents/123   --> 204 (everything okay, please proceed)
GET /documents/123       --> 303 redirect to `/documents/abc`

此时,浏览器不会在/documents/abc 处找到实际资源,而不是GETting

XMLHttpRequest cannot load http://localhost:8000/people/username/nschloe. 
The request was redirected to 'http://localhost:8000/people/YDHa-B2FhMie', 
which is disallowed for cross-origin requests that require preflight.

此行为符合the standard

7.1.5 带预检的跨域请求

如果响应的 HTTP 状态码不在 2xx 范围内

应用网络错误步骤。

这似乎意味着一个不能对经过身份验证的资源进行重定向,即使重定向位于同一个域 (localhost)。

这真的是真的吗?有通用的解决方法吗?

【问题讨论】:

  • 你的响应头是什么样的?尤其是 Access-Control-Allow-Headers?
  • 对于预检OPTIONS 请求,我有Access-Control-Allow-Headers:Accept, Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, Accept-Encoding
  • 你的意思是这是重定向的 url /documents/abc 对吧?
  • 嗯,他们反对任何会导致重定向的事情,因为这可能会导致安全问题。如果之前的请求被授权,您可以随时向客户端发出另一个请求。
  • 后端当然可以不小心将客户端重定向到其他网站并包含令牌。我称之为(安全)错误,而不是标准需要规定的东西。重定向到另一个资源(即使它不是Same-Origin)是一个完全有效的用例恕我直言。

标签: http redirect cors preflight


【解决方案1】:

在成功的 CORS 预检后,原始标准确实排除了重定向。 Quoting § 7.1.5.3:

这是实际的请求。提出请求时应用提出请求的步骤并遵守以下请求规则。

  • 如果响应的 HTTP 状态代码为 301、302、303、307 或 308 应用缓存和网络错误步骤。

由于您的努力(谢谢!),2016 年 8 月 4 日,标准是 updated,以允许在成功的 CORS 预检检查后重定向。

在浏览器赶上之前,唯一可行的选择似乎是以下一种或多种:

  1. 仅为simple requests 发出重定向。
  2. 发出305 redirect,在Location 标头中使用您自己的URL 作为“代理”。为有限的浏览器支持做好准备,因为 305 已被弃用。
  3. 做一个虚假的“重定向”:
  • 使用meta refresh 和/或Javascript Location 更改返回HTML。
  • 返回具有视口填充iframe 的 HTML,并将重定向目标作为 iframe 的源。
  • 显示用户必须单击才能访问内容的链接。

【讨论】:

  • 浏览器交付此类更改的预期时间是多少?在最新的 chrom/firefox 中它仍然是一个问题。
  • @freakman 根据我的经验,所有主流浏览器的最新版本的标准更改和实施之间大约有两年的延迟。特定浏览器可能会更新得更快,但我会说是 2018 年 8 月全面更新。
  • 您甚至可以生成一个自动点击隐藏链接的 HTML 页面。如果支持 HTTP POST,那么即使是隐藏的表单也可以提交到目标端点
  • 对此has landed in the Blink/Chromium sources 的修复并将在 Chrome 57 中发布(我认为目标是在 3 月中旬的某个时间发布)。
  • @NitinRastogi 我认为您遇到的问题是另一个问题。对规范和 Chrome 57 所做的更改是,如果服务器以 200 或 204 响应预检 OPTIONS 并且 then 以 30x 响应后续 GET,则 Chrome 57+ 将现在跟随重定向而不是发出错误。但是在您的情况下,问题似乎是服务器使用 302 响应 OPTIONS 请求本身。根据 CORS(Fetch)规范,对 OPTIONS 请求本身的 302 响应不是对预检的可接受响应。因此,您看到的错误。
猜你喜欢
  • 2021-10-10
  • 1970-01-01
  • 1970-01-01
  • 2019-01-04
  • 2022-01-16
相关资源
最近更新 更多