当 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?
我有一个网站,React 前端位于(比方说)app.mydomain.com 和 api 位于 api.mydomain.com。
用户向 API 提交登录请求,并在成功登录后收到一个不错的 cookie,以便稍后使用。 front-end 仅直接与 API 对话,因此 cookie 上的域只需设置为 api.mydomain.com.
我使用 Axios 执行 withCredentials
标志设置为 true 的请求,以便接收 cookie。
服务器上允许CORS的headers如下:
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 says they do not allow "wildcarding" the Origin value, not the Headers one, same in this page,这里什么都没有提到。
为什么 Firefox 会这样,为什么在我能找到的任何地方都没有提到它?
在包含 Access-Control-Allow-Credentials: true
的预检响应中,用作 header Access-Control-Allow-Headers
值的星号按字面解释,而不是通配符(即“所有 headers 允许").
关于 Access-Control-Allow-Headers
header 的主要 MDN page about CORS doesn't explicitly state this rule. However, the more specific MDN page 确实如此明确:
The value "*
" only counts as a special wildcard value for requests without credentials (requests without HTTP cookies or HTTP authentication information). In requests with credentials, it is treated as the literal header name "*
" without special semantics. Note that the Authorization
header can't be wildcarded and always needs to be listed explicitly.
这里引用了更权威的 Fetch standard:
的澄清引述
For Access-Control-Expose-Headers
, Access-Control-Allow-Methods
, and Access-Control-Allow-Headers
response headers, the value *
counts as a wildcard for requests without credentials.
Access-Control-Expose-Headers
, Access-Control-Allow-Methods
, and Access-Control-Allow-Headers
response headers can only use *
as value when request’s credentials mode is not "include
".
(我的重点)
规范规定的浏览器的相关规范要求在 main fetch 算法中 https://fetch.spec.whatwg.org/#main-fetch,在步骤 13,子步骤 2:
If request's credentials mode is not
"include
" and headerNames contains *
, then set response’s CORS-exposed header-name list to all unique header names in response’s header list.
换句话说,规范声明要求 *
的浏览器行为是:
- 如果凭据模式不是“
include
”,浏览器需要检查响应中的实际响应列表header,并允许所有这些
- 如果凭据模式是“
include
”,浏览器需要只允许任何响应header字面名称“[=13” =]"
在这一步的最后,实际上有一条注释说了几乎相同的事情:
One of the headerNames can still be *
at this point, but will only match a header whose name is *
.
我有一个网站,React 前端位于(比方说)app.mydomain.com 和 api 位于 api.mydomain.com。
用户向 API 提交登录请求,并在成功登录后收到一个不错的 cookie,以便稍后使用。 front-end 仅直接与 API 对话,因此 cookie 上的域只需设置为 api.mydomain.com.
我使用 Axios 执行 withCredentials
标志设置为 true 的请求,以便接收 cookie。
服务器上允许CORS的headers如下:
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 says they do not allow "wildcarding" the Origin value, not the Headers one, same in this page,这里什么都没有提到。
为什么 Firefox 会这样,为什么在我能找到的任何地方都没有提到它?
在包含 Access-Control-Allow-Credentials: true
的预检响应中,用作 header Access-Control-Allow-Headers
值的星号按字面解释,而不是通配符(即“所有 headers 允许").
关于 Access-Control-Allow-Headers
header 的主要 MDN page about CORS doesn't explicitly state this rule. However, the more specific MDN page 确实如此明确:
The value "
*
" only counts as a special wildcard value for requests without credentials (requests without HTTP cookies or HTTP authentication information). In requests with credentials, it is treated as the literal header name "*
" without special semantics. Note that theAuthorization
header can't be wildcarded and always needs to be listed explicitly.
这里引用了更权威的 Fetch standard:
的澄清引述For
Access-Control-Expose-Headers
,Access-Control-Allow-Methods
, andAccess-Control-Allow-Headers
response headers, the value*
counts as a wildcard for requests without credentials.
Access-Control-Expose-Headers
,Access-Control-Allow-Methods
, andAccess-Control-Allow-Headers
response headers can only use*
as value when request’s credentials mode is not "include
".
(我的重点)
规范规定的浏览器的相关规范要求在 main fetch 算法中 https://fetch.spec.whatwg.org/#main-fetch,在步骤 13,子步骤 2:
If request's credentials mode is not "
include
" and headerNames contains*
, then set response’s CORS-exposed header-name list to all unique header names in response’s header list.
换句话说,规范声明要求 *
的浏览器行为是:
- 如果凭据模式不是“
include
”,浏览器需要检查响应中的实际响应列表header,并允许所有这些 - 如果凭据模式是“
include
”,浏览器需要只允许任何响应header字面名称“[=13” =]"
在这一步的最后,实际上有一条注释说了几乎相同的事情:
One of the headerNames can still be
*
at this point, but will only match a header whose name is*
.