首页 > 解决方案 > 当 Allow-Credentials 设置为 true 时,为什么我不能在 Access-Control-Allow-Headers 上使用通配符 *?

问题描述

我有一个网站,React 前端驻留在(比方说)app.mydomain.com 和 api.mydomain.com 上的 api。

用户向 API 提交登录请求,并在成功登录后收到一个不错的 cookie,供以后使用。前端仅直接与 API 对话,因此 cookie 上的域只需设置为 api.mydomain.com。

我使用 Axios 执行将withCredentials标志设置为 true 的请求,以便接收 cookie。

服务器上允许 CORS 的标头如下:

Access-Control-Allow-Origin: http://app.mydomain.com
Access-Control-Allow-Methods: GET,POST,DELETE,PUT,OPTIONS
Access-Control-Allow-Headers: *
Access-Control-Allow-Credentials: true

在这种情况下,这是来自 Firefox 的响应:

将允许标题设置为通配符时出现 Firefox 错误

但是,一旦Access-Control-Allow-Headers更具体地设置了值,比如说 Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept,一切正常。

Mozilla 表示他们不允许“通配符” Origin 值,而不是 Headers 值,在此页面中相同,此处未提及任何内容。

为什么 Firefox 会有这样的行为,为什么在我能找到的任何地方都没有提到它?

标签: firefoxcors

解决方案


在包含 的预检响应中Access-Control-Allow-Credentials: true,用作标头值的星号按Access-Control-Allow-Headers字面意思解释,而不是通配符(即“允许所有标头”)。

确实,关于 CORS 的 MDN 主页并没有明确说明此规则。但是,关于标头的更具体的MDN 页面Access-Control-Allow-Headers明确地这样做了:

对于没有凭据的请求(没有 HTTP cookie 或 HTTP 身份验证信息的请求) ,值 " *" 仅算作一个特殊的通配符值。在带有凭据的请求中,它被视为*没有特殊语义的文字标头名称“”。请注意,Authorization标头不能使用通配符,并且始终需要明确列出。

以下是来自更权威的Fetch 标准的澄清引用:

对于Access-Control-Expose-HeadersAccess-Control-Allow-MethodsAccess-Control-Allow-Headers响应标头,对于没有凭据的请求*,该值计为通配符。

Access-Control-Expose-Headers, Access-Control-Allow-Methods, 和Access-Control-Allow-Headers响应标头只能在请求的凭据模式不是 " "*时用作值。include

(我的重点)


规范规定的浏览器的相关规范要求在https://fetch.spec.whatwg.org/#main-fetch的主要获取算法中,在步骤 13 的子步骤 2 中:

如果request凭证模式不是 " include" 并且headerNames包含*,则将responseCORS-exposed header-name 列表设置为responseheader列表中的所有唯一标头 名称

换句话说,spec 语句要求的浏览器行为*是:

  • 如果凭据模式不是include”,则浏览器需要检查响应中的实际响应头列表,并允许所有这些
  • 如果凭据模式include”,则要求浏览器只允许任何带有文字名称“ *”的响应标头

在该步骤的最后,实际上有一个注释说几乎相同的事情:

其中一个headerNames仍然可以*在这一点上,但只会匹配名称为*.


推荐阅读