本地开发环境XHR跨域请求未携带Secure属性Cookie问题排查
问题场景
- 本地通过CRA启动React应用,默认监听
localhost:3000端口,使用axios发起接口请求 - 首次调用接口
https://api-local.domain.io:3010/xxx/authorize,接口返回如下Set-Cookie响应头:
set-cookie: gd_resource=XXX; Domain=.domain.io; Path=/; Expires=Thu, 23 Jun 2022 16:08:05 GMT; Secure; SameSite=None
- 按照Cookie配置预期,所有向
*.domain.io子域发起的请求都应自动携带该Cookie,且该Cookie要求必须配置Secure属性 - 实际异常:后续调用
https://project-dev.domain.io/yyy接口时,请求头中未携带上述gd_resourceCookie - 已尝试的排查操作:
- 怀疑是本地HTTP环境导致,修改
/etc/hosts将前端访问地址改为http://editor-local.domain.io:3000,问题无改善 - 尝试通过mkcert签发证书,将前端运行在
https://localhost:3000,Chrome提示证书无效(系统钥匙串已标记证书可信) - 后续通过mkcert成功将前端运行在
https://editor-local.domain.io:3000的HTTPS环境,请求仍然未携带目标Cookie
- 怀疑是本地HTTP环境导致,修改
核心原因排查
这个问题本质是跨域场景下Cookie的写入、携带没有满足浏览器的安全限制,按优先级从高到低查以下点就行,不用反复试环境配置:
- Cookie直接过期了:你贴的
Set-Cookie头里Expires写的是2022年6月23日,到现在早就过了有效期,浏览器碰到过期Cookie会直接清理,根本不会存入本地存储,后续请求自然不可能带上。这是最容易忽略的低级问题,第一个查这个。 - 前端没开跨域带凭证的配置:axios默认不会在跨域请求里带Cookie,必须手动开
withCredentials:// 全局生效配置 axios.defaults.withCredentials = true // 如果你是自己封装的axios实例,在实例配置里加 const request = axios.create({ baseURL: 'xxx', withCredentials: true }) - 后端CORS配置没配对:跨域场景下要让Cookie正常写入、正常携带,后端两个配置必须满足,少一个浏览器都会直接拦截:
- 所有涉及跨域的接口(包括第一次种Cookie的authorize接口、后面的业务接口),响应头必须带
Access-Control-Allow-Credentials: true Access-Control-Allow-Origin绝对不能设成通配符*,必须精确匹配你当前前端的源地址,比如你现在前端跑在https://editor-local.domain.io:3000,这个头的值就得一字不差是这个地址,协议、端口错了都不行。
- 所有涉及跨域的接口(包括第一次种Cookie的authorize接口、后面的业务接口),响应头必须带
- Cookie属性和访问协议不匹配:你给Cookie加了
Secure; SameSite=None属性,这种Cookie只会在HTTPS环境下被浏览器接受写入,HTTP环境下会直接被拦截,这也是你最开始改hosts用HTTP访问域名时完全没效果的核心原因。你现在已经把前端切到HTTPS,这部分要求已经满足了。 - 本地证书不被信任的问题:之前你用mkcert给localhost签证书Chrome报无效,是因为生成证书的时候没把要访问的域名/IP加到主体备用名称列表里,生成的时候直接执行
mkcert editor-local.domain.io localhost 127.0.0.1,把所有本地要访问的地址都加进去,签出来的证书Chrome就会正常识别信任。
验证步骤
按顺序走一遍就能解决:
- 先让后端把Cookie的过期时间改对,设成未来的有效时间,或者干脆不设
Expires用会话级Cookie,关闭浏览器才失效 - 前端所有跨域请求都开启
withCredentials: true - 让后端修改CORS配置,满足上面说的凭证携带要求
- 调用完authorize接口后,打开Chrome DevTools -> Application -> Cookies,找到对应域名的存储,确认
gd_resource已经正常写入,Domain、Secure、SameSite、过期时间这些属性都符合预期 - 再调用后续业务接口,查看请求头里的Cookie字段就会看到对应值被正常携带
内容的提问来源于stack exchange,提问作者AlexandreS
相关产品推荐
相关产品推荐

