Laravel 12 + Sanctum 实现跨子域 Cookie 认证需满足同根域名前提,SESSION_DOMAIN=.example.com 且 SANCTUM_STATEFUL_DOMAINS=app.example.com;若域名无关则只能退至 Token 模式。

SPA 前后端部署在不同域名(比如前端 https://app.example.com,后端 API 在 https://api.example.com)时,Laravel 12 + Sanctum 要实现 Cookie 认证(即“登录态共享”),关键不是让 Cookie 跨完全无关域名(如 example.com 和 other-site.net),而是必须满足「同根域名」前提——也就是前后端都属于 example.com 下的子域。
SESSION_DOMAIN 必须设为带点的根域名
这是跨子域共享 laravel_session 和 XSRF-TOKEN 的基础:
-
正确写法:
SESSION_DOMAIN=.example.com(开头必须有.) - 这样浏览器会把 Cookie 同时发给
app.example.com、api.example.com、admin.example.com等所有子域 -
错误写法:
SESSION_DOMAIN=example.com(没点)→ 仅匹配精确域名,不下发到子域;SESSION_DOMAIN=app.example.com→ 只给前端域,后端收不到
SANCTUM_STATEFUL_DOMAINS 只填前端完整子域名
Sanctum 用它判断哪些请求走 Session 认证(而非 fallback 到 token 认证):
由 ReMe 驱动的记忆管理系统,支持跨会话记忆持久化、自动应用用户偏好以及智能上下文压缩...
-
只写前端地址:
SANCTUM_STATEFUL_DOMAINS=app.example.com - 多个用英文逗号分隔:
SANCTUM_STATEFUL_DOMAINS=app.example.com,dev-app.example.com -
不要加协议、端口、路径或通配符:❌
https://app.example.com❌app.example.com:3000❌*.example.com - 后端 API 域名(如
api.example.com)不用也不该写进这里——它只是接收请求的一方,不是发起请求的“可信前端”
配套配置不能漏
光改这两个变量还不够,还需同步检查:
-
config/session.php中:'secure' => true(HTTPS 环境下必须为true;HTTP 环境下才设false) -
'same_site' => 'lax'(推荐值,兼顾安全性与子域兼容性) -
config/sanctum.php中确保'stateful'是通过explode(',', env('SANCTUM_STATEFUL_DOMAINS'))动态读取,不要硬编码或拼接APP_URL - 前端调用
/sanctum/csrf-cookie后,务必在浏览器 DevTools → Application → Cookies 中确认:
–XSRF-TOKEN和laravel_session的 Domain 列显示为.example.com
– 且后续登录请求(如POST /login)的请求头中包含Cookie: XSRF-TOKEN=xxx; laravel_session=yyy
如果真不在同一根域名下
比如前端是 myapp.com,后端是 api.theirdomain.com,则无法共享 Cookie —— 此时 Sanctum 的 Session 模式失效,只能退回到 Token 模式:
- 前端登录后,后端返回
Bearertoken($user->createToken('web')->plainTextToken) - 前端将 token 存入内存(非 localStorage),后续所有请求带
Authorization: Bearer xxx - 路由统一用
middleware('auth:sanctum'),无需配置stateful域名 - 注意:这种模式下 CSRF 保护自动关闭,需靠 token 本身防重放和过期机制保障安全

















