提问人:Francesco 提问时间:8/16/2021 最后编辑:jonrsharpeFrancesco 更新时间:1/15/2023 访问量:2047
当 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.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 的响应:
但是,一旦更具体地设置了值,比如说 ,一切正常。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
编辑 (2023):正如 sideshowbarker 在他的评论中指出的那样,关于 CORS 的 MDN Web Docs 页面已经更新,现在声明如下:
响应凭证请求时:[...]
- 服务器不得为响应标头值指定 “” 通配符,而必须指定标头名称的显式列表;例如
*
Access-Control-Allow-Headers
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
以下是来自更权威的 Fetch 标准的澄清引用:
对于 、 和 响应标头,该值计为没有凭据的请求的通配符。
Access-Control-Expose-Headers
Access-Control-Allow-Methods
Access-Control-Allow-Headers
*
Access-Control-Expose-Headers
、 和 响应标头只能在请求的凭据模式不是“include
”时用作值。Access-Control-Allow-Methods
Access-Control-Allow-Headers
*
(我的重点)
规范中对浏览器的相关规范要求在 https://fetch.spec.whatwg.org/#main-fetch 的主获取算法中,在步骤 13 的子步骤 2 中:
如果请求的凭据模式不是 “” 和 headerNames 包含 ,然后将响应的 CORS 公开的标头名称列表设置为响应标头列表中的所有唯一标头名称。
include
*
换句话说,spec 语句要求的浏览器行为是:*
- 如果凭据模式不是 “”,则浏览器需要检查响应中响应标头的实际列表,并允许所有响应标头
include
- 如果凭据模式为 “”,则浏览器需要仅允许任何具有文本名称”
include
*
"
在这一步的最后,实际上有一条注释说了几乎相同的事情:
此时,其中一个 headerNames 仍可能存在,但只会匹配名称为 的标头。
*
*
评论
*
*