预检和重定向的CORS请求:不允许.解决方法?

Nic*_*mer 24 redirect http cors preflight

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

GET /documents/123  --> 303 redirect to `/documents/abc`
GET /documents/abc  --> 200
Run Code Online (Sandbox Code Playgroud)

一切顺利.

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

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

此时,浏览器产生的不是GET实际资源/documents/abc

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.
Run Code Online (Sandbox Code Playgroud)

此行为符合标准:

7.1.5带预检的跨源请求

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

应用网络错误步骤.

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

这真的可以吗?有一个共同的解决方法吗?

bis*_*hop 16

在成功进行CORS预检后,原始标准确实排除了重定向.引用§7.1.5.3:

这是实际的要求.在发出请求时,应用make a request步骤并遵守下面的请求规则.

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

由于您的努力(谢谢!),8月4日更新标准以允许在成功进行CORS预检检查后重定向.

在浏览器迎头赶上之前,唯一可行的选择似乎是一个或组合:

  1. 问题重定向仅适用于简单请求.
  2. 发出305重定向,Location标题中有您自己的URL 作为"代理".准备好有限的浏览器支持,因为不推荐使用305.
  3. 做一个虚假的"重定向":
    • 使用meta refresh和/或Javascript Location更改返回HTML .
    • 返回具有视口填充的HTML,iframe将重定向目标作为iframe的源.
    • 显示用户必须单击以访问内容的链接.

  • @NitinRastogi我认为你遇到的问题是另一个问题.对规范和Chrome 57进行的更改是,如果服务器以200或204响应预检选项和*然后*以30x响应后续GET,那么Chrome 57+现在将遵循重定向而不是发出错误.但在您的情况下,问题似乎是服务器使用302响应OPTIONS请求本身.根据CORS(获取)规范,对OPTIONS请求本身的302响应不是对预检的可接受响应.因此你看到的错误. (3认同)
  • 什么是浏览器提供像这样的更改的预期时间?它仍然是最新的chrom/firefox中的一个问题. (2认同)
  • @freakman根据我的经验,在所有主流浏览器的最新版本中,标准更改和实现之间存在两年的延迟.特定的浏览器可能会更快地更新,但我会说是2018年8月. (2认同)
  • 对此问题的修复[已在 Blink/Chromium 源代码中](https://chromium.googlesource.com/chromium/src/+/eaeb7a5f8e9432594d8bcc09956c1f50e8f0ba66) 中发布,并将在 Chrome 57 中发布(预计于 3 月中旬发布)思考)。 (2认同)