firefox - 当 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 的响应:
但是,一旦Access-Control-Allow-Headers
更具体地设置了值,比如说
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
,一切正常。
Mozilla 表示他们不允许“通配符” Origin 值,而不是 Headers 值,在此页面中相同,此处未提及任何内容。
为什么 Firefox 会有这样的行为,为什么在我能找到的任何地方都没有提到它?
解决方案
在包含 的预检响应中Access-Control-Allow-Credentials: true
,用作标头值的星号按Access-Control-Allow-Headers
字面意思解释,而不是通配符(即“允许所有标头”)。
确实,关于 CORS 的 MDN 主页并没有明确说明此规则。但是,关于标头的更具体的MDN 页面Access-Control-Allow-Headers
明确地这样做了:
对于没有凭据的请求(没有 HTTP cookie 或 HTTP 身份验证信息的请求) ,值 "
*
" 仅算作一个特殊的通配符值。在带有凭据的请求中,它被视为*
没有特殊语义的文字标头名称“”。请注意,Authorization
标头不能使用通配符,并且始终需要明确列出。
以下是来自更权威的Fetch 标准的澄清引用:
对于
Access-Control-Expose-Headers
、Access-Control-Allow-Methods
和Access-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包含*
,则将response的CORS-exposed header-name 列表设置为response的header列表中的所有唯一标头 名称。
换句话说,spec 语句要求的浏览器行为*
是:
- 如果凭据模式不是“
include
”,则浏览器需要检查响应中的实际响应头列表,并允许所有这些 - 如果凭据模式为“
include
”,则要求浏览器只允许任何带有文字名称“*
”的响应标头
在该步骤的最后,实际上有一个注释说几乎相同的事情:
其中一个headerNames仍然可以
*
在这一点上,但只会匹配名称为*
.
推荐阅读
- javascript - 如何以特定格式显示当前日期和时间?
- sql - 为什么“DD/MM/YYYY”在过滤器中不起作用?
- javascript - 错误 [ERR_HTTP_HEADERS_SENT]:在 ServerResponse.setHeader (_http_outgoing.js:518:11) 将标头发送到客户端后无法设置标头
- apache-kafka - Flink - 如何使用 withTimestampAssigner 从事件有效负载中获取时间(不使用 Kafka 时间戳)
- javascript - 从 uri 或 require 对本机图像源做出反应
- elixir - Elixir Simple 模块仅产生“参数错误”
- java - 如何分配一个长的十六进制值,我应该在 Java 中将它分配给什么数据类型?
- javascript - Quill.js 不断从锚标签中剥离类
- python - 如何重命名通过 Django Rest Framework 上传的图像
- python - 如何卸载并重新安装 anaconda naviator