29

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

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

一切都很顺利。

让我们向Authorization发送标头的同一端点发出经过身份验证的请求。这使请求成为预检请求,浏览器执行预检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.

这种行为符合标准

7.1.5 带预检的跨域请求

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

应用网络错误步骤。

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

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

4

1 回答 1

18

原始标准确实排除了成功 CORS 预检后的重定向。引用第 7.1.5.3 节

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

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

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

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

  1. 仅针对简单请求发出重定向。
  2. 发出305 重定向,在标头中使用您自己的 URLLocation作为“代理”。为有限的浏览器支持做好准备,因为 305 已被弃用。
  3. 做一个假的“重定向”:
  • meta refresh返回带有和/或 JavascriptLocation更改的HTML 。
  • 返回具有视口填充iframe的 HTML,其中重定向目标作为 iframe 的源。
  • 显示用户必须单击才能访问内容的链接。
于 2016-09-27T15:10:13.390 回答