当 Allow-Credentials 设置为 true 时,为什么不能在 Access-Control-Allow-Headers 上使用通配符 *?

Why can't I use a wildcard * on Access-Control-Allow-Headers when Allow-Credentials is set to true?

提问人:Francesco 提问时间:8/16/2021 最后编辑:jonrsharpeFrancesco 更新时间:1/15/2023 访问量:2047

问:

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

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

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

服务器上允许 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 error when allow-headers is set to wildcard

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

Mozilla表示,他们不允许“通配符”Origin值,而不是Headers值,在此页面中也是如此,其中没有提到任何内容。

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

Firefox CORS

评论

1赞 jonrsharpe 8/16/2021
developer.mozilla.org/en-US/docs/Web/HTTP/Headers/... 仅允许没有凭据的请求。你有没有发现Firefox的行为与其他浏览器不同?*
0赞 Francesco 8/16/2021
您引用的页面确实回答了我的问题。同时,我期待Firefox部分更加清晰:截至目前,它只是在启用凭据时警告Allow-Origin是否设置为“*”,但浏览器没有特别清楚关于标头设置
1赞 sideshowbarker 8/18/2021
developer.mozilla.org/en-US/docs/Web/HTTP/......已更新,以包含有关在响应凭据请求时禁止在 Access-Control-Allow-Headers 标头中使用通配符的限制的信息。非常感谢 — 因为你让三件好事发生了:(1) 你在这里提出了这个问题并引用了那个 MDN 文档,(2) 你引起了 SO 贡献者的注意,他花时间写了一个高质量的答案,以及 (3) 导致 MDN 文档的缺陷被 MDN 贡献者识别出来, 谁有足够的动力来更新它。*
1赞 sideshowbarker 8/18/2021
一个要求:今后,每当你在 MDN 文章中遇到内容问题/缺点时,请考虑 github.com/mdn/content/issues/new/choose 提出问题。您甚至可以考虑自己直接更新内容(例如,在 github.com/mdn/content/edit/main/files/en-us/web/http/cors/...),并按照 github.com/mdn/content#simple-changes 的指导提交拉取请求。所有的 MDN 源代码都在 GitHub 中,许多源代码都在 Markdown 中(最终都会如此),所以这大致就像写一个好的 Stack Overflow 答案一样简单

答:

4赞 jub0bs 8/16/2021 #1

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

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

值 “” 仅计为没有凭据的请求(没有 HTTP Cookie 或 HTTP 身份验证信息的请求)的特殊通配符值。在具有凭据的请求中,它被视为没有特殊语义的文本标头名称 “”。请注意,标头不能使用通配符,并且始终需要显式列出。**Authorization

编辑 (2023):正如 sideshowbarker 在他的评论中指出的那样,关于 CORS 的 MDN Web Docs 页面已经更新,现在声明如下:

响应凭证请求时:[...]

  • 服务器不得为响应标头值指定 “” 通配符,而必须指定标头名称的显式列表;例如*Access-Control-Allow-HeadersAccess-Control-Allow-Headers: X-PINGOTHER, Content-Type

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

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

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

(我的重点)


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

如果请求凭据模式不是 “” 和 headerNames 包含 ,然后将响应的 CORS 公开的标头名称列表设置为响应标头列表中的所有唯一标头名称include*

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

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

在这一步的最后,实际上有一条注释说了几乎相同的事情:

此时,其中一个 headerNames 仍可能存在,但只会匹配名称为 的标头。**