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

CORS request with Preflight and redirect: disallowed. Workarounds?

我正在设计一个 API 允许用户进行身份验证(使用令牌)并且包含同一域内的重定向。现在,对于 returns 303,

端点的未经身份验证的请求
GET /documents/123  --> 303 redirect to `/documents/abc`
GET /documents/abc  --> 200

一切顺利。

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

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

此时,浏览器不会 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.

此行为符合 the standard:

7.1.5 Cross-Origin Request with Preflight

If the response has an HTTP status code that is not in the 2xx range

Apply the network error steps.

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

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

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

This is the actual request. Apply the make a request steps and observe the request rules below while making the request.

  • If the response has an HTTP status code of 301, 302, 303, 307, or 308 Apply the cache and network error steps.

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

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

  1. 仅为 simple requests 发送重定向。
  2. 发布一个305 redirect,用你自己的URL在Locationheader作为“代理”。为有限的浏览器支持做好准备,因为 305 已被弃用。
  3. 做一个假的“重定向”:
  • returnHTML与meta refreshand/orJavascriptLocation变化。
  • return HTML 有一个 viewport-filling iframe 将重定向目标作为 iframe 的源。
  • 显示用户必须单击才能访问内容的 link。