先记住这个答案
fetch 的 credentials 决定是否携带 Cookie、TLS 证书等凭据,以及是否接受 Set-Cookie。默认 same-origin,同源发送并接收,跨域忽略;omit 全部不处理;include 跨域也发,但服务端须返回 Access-Control-Allow-Credentials: true 且 Access-Control-Allow-Origin 不能为 *。开发时要按需选择,跨域登录接口需 include 并配置服务端。
- 默认 same-origin,跨域不带 Cookie
- include 跨域携带,需服务端允许凭据
- omit 完全禁用凭据发送与接收
credentials 的三种取值机制
credentials 选项控制两点:它决定浏览器在发送请求时是否自动附加已经存储的 Cookie、TLS 客户端证书和认证头,也决定响应中的 Set-Cookie 是否会被浏览器接受并更新存储。默认值是 same-origin,因此只有同源请求会发送 Cookie 并接收 Set-Cookie,跨域请求默认被丢弃。
当设定为 omit,表示请求和响应都不携带任何凭据,即使同源也如此。include 则相反,跨域请求也会携带目标域名下的 Cookie,并接受响应中的 Set-Cookie。但 include 模式必须满足 CORS 配置,服务端响应需返回 Access-Control-Allow-Origin 指定源且 Access-Control-Allow-Credentials 为 true,缺少前者或使用通配符都会使浏览器拒绝。
跨子域共享登录状态时的配置
假设前端页面位于 https://pay.example.org,需要向 https://api.example.com 提交订单。由于跨域,fetch 默认不带 Cookie,接口无法识别登录用户,返回 401。修改请求为 credentials: 'include' 后,浏览器会追加 api.example.com 域名下的 Cookie,但服务端必须设置响应头 Access-Control-Allow-Origin: https://pay.example.org 和 Access-Control-Allow-Credentials: true,否则请求被 CORS 阻断并抛出 TypeError。
另一个细节是跨域 include 时浏览器附加的是请求目标域的 Cookie,因此需要在 api.example.com 下种过登录态 Cookie。实际操作时,应先用 document.cookie 或认证接口种下 Cookie,再调用业务接口。如果服务端缺少允许凭据的头,开发者可在控制台看到一个 CORS 错误,fetch 的 Promise 会进入 catch 并得到 TypeError,而不会返回响应。
容易失效的配置与判断
include 模式并非万无一失,即使服务端正确返回了 CORS 允许凭据的头,Cookie 也不一定被携带。例如 SameSite 属性会阻止第三方 Cookie 在跨站请求中发送,Chrome 95 后默认 Lax,如果 Cookie 未显式设置 SameSite=None; Secure 则无法在跨站请求中带上。此时应检查 Cookie 的 SameSite 设置并调整。
判断最终是否生效,应通过网络面板查看请求头是否出现 Cookie,以及响应中的 Set-Cookie 是否被接受。如果选择 omit,则一切凭据都被忽略,且响应中 Set-Cookie 也不会应用,这在一些登录验证场景可能造成循环。实际开发中建议默认使用 same-origin,只在确定需要跨域携带登录态时才开启 include,并同步调整服务端配置,避免未授权的暴露。
容易答错的地方
- 跨域 fetch 设置 include 就能带 Cookie
- 错误。浏览器还会验证服务端返回的 Access-Control-Allow-Origin 和 Access-Control-Allow-Credentials,格式不符会直接阻止响应,导致请求失败。
- credentials 只控制请求,不影响响应
- 错误。它同样控制浏览器是否接受响应中的 Set-Cookie,如果设为 omit,同源请求也不会种下 Cookie。
面试官还会怎么问?
跨域 fetch 的 include 模式下,发送的 Cookie 从哪里获取?
浏览器会从请求 URL 对应的域中寻找匹配的 Cookie 并附加,而不是从源页面域取。因此登录必须发生在目标域上,才能通过带凭据的请求保持状态。
fetch 的 credentials 和 XMLHttpRequest 的 withCredentials 有何异同?
XHR 默认 withCredentials 为 false,同源请求仍会发送 Cookie,跨域不发送;fetch 默认 same-origin 也是同源发送、跨域不发送。效果上,withCredentials=true 相当于 fetch credentials:'include',都会跨域发送,但 fetch 还提供 omit 等更多选项,错误处理也存在差异。
如果将 credentials 设为 'same-origin' 用于跨域请求,会有异常吗?
不会,浏览器忽略跨域请求的 Cookie,行为等同于不带 Cookie,但请求本身正常发出,不受 CORS 凭据规则限制。因此大多数场景默认同源即可,无需调成 omit。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。