主题
Cookie 与跨站策略
Cookie 的问题往往不在“怎么设置”,而在“什么时候会发送、什么时候不会发送,以及浏览器为什么拦”。这通常会和同源策略、跨站请求、CORS、SameSite 一起出现。
先区分两个概念
同源
同源要求协议、主机、端口都相同。
md
https://app.example.com:443
https://app.example.com:443 // 同源
https://api.example.com:443 // 不同源
http://app.example.com:443 // 不同源同站
同站更关注站点归属,通常看注册域名是否相同。
md
app.example.com
api.example.com这两个域通常不同源,但属于同站。
Cookie 为什么跨域时经常“不带上”
跨域请求时,Cookie 是否发送要同时看:
fetch/ XHR 是否允许携带凭证。- 服务端 CORS 是否允许凭证。
- Cookie 自身的
SameSite是否允许当前场景发送。 - 浏览器是否拦截第三方 Cookie。
只满足其中一部分通常还不够。
SameSite 的影响
SameSite=Strict
最严格。跨站请求通常都不会带上 Cookie。
SameSite=Lax
多数场景下的默认推荐值。
- 普通跨站子请求通常不带。
- 某些顶级导航场景可以带。
SameSite=None
允许跨站发送 Cookie,但必须同时设置 Secure。
http
Set-Cookie: sessionId=abc; Path=/; SameSite=None; Secure; HttpOnly前端想携带 Cookie 还需要做什么
以 fetch 为例,需要显式设置:
js
fetch('https://api.example.com/user', {
credentials: 'include',
})如果不写 credentials: 'include',浏览器通常不会在跨域请求里携带 Cookie。
服务端还需要配什么
服务端必须允许凭证跨域:
http
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true注意:
Access-Control-Allow-Origin不能是*- 必须返回具体来源
一个完整链路
前端页面在:
md
https://app.example.com接口服务在:
md
https://api.example.com如果希望请求自动带上登录 Cookie,需要同时满足:
- Cookie 设置为
SameSite=None; Secure - 前端请求写
credentials: 'include' - 服务端返回
Access-Control-Allow-Credentials: true - 服务端返回明确的
Access-Control-Allow-Origin
为什么有时本地开发能用,线上反而不行
常见原因有:
- 本地是同源代理,线上变成跨域
- 线上走 HTTPS,但 Cookie 没配
Secure - Cookie 仍是
SameSite=Lax - 跨域接口响应写了
Access-Control-Allow-Origin: * - 浏览器阻止第三方 Cookie
第三方 Cookie
当一个站点中的资源请求属于另一个站点上下文时,相关 Cookie 常会被视为第三方 Cookie。现代浏览器对第三方 Cookie 限制越来越严格,因此不能把“跨站一定能带 Cookie”当成理所当然。
开发建议
- 同站不同子域的前后端项目,优先先明确“是否跨源、是否跨站”。
- 登录态如果依赖 Cookie,优先把
SameSite、Secure、HttpOnly、CORS 配套一起看。 - 排查 Cookie 问题时,不要只看请求代码,要同时看响应头和浏览器策略。
- 业务允许时,优先用同源代理降低跨域与 Cookie 策略复杂度。
