Sanctum 不能直接用 auth:api 中间件,因其默认未注册 api guard,实际使用 sanctum guard;API 路由须用 auth:sanctum,SPA 场景走 session+CSRF,纯 API 调用需带 Bearer token;Sanctum::user() 为 null 多因中间件未绑定 sanctum guard;token 不宜依赖 expires_at,推荐主动撤销与定期清理。

Sanctum 为什么不能直接用 auth:api 中间件?
因为 Sanctum 默认不注册 api guard,你配了 auth:api 会报错 Auth guard [api] is not defined。它走的是 web guard 的 session 路径(SPA 场景),或 token-based 的轻量验证(API 场景),但两者底层 guard 名是 sanctum,不是 api。
实操建议:
- 检查
config/auth.php,确认'defaults' => ['guard' => 'web'],且guards.sanctum存在并启用 - API 路由必须用
auth:sanctum中间件,不是auth:api - 若你坚持用
auth:api,得手动在guards里加一个指向sanctumdriver 的apiguard —— 但没必要,反而容易混淆
POST /login 返回 419 或 401?Token 没发对还是没带 header?
419 是 CSRF 失败,说明你用了 web guard 流程(比如从 Vue 页面发请求但没传 X-XSRF-TOKEN);401 是 token 验证失败,大概率是 Authorization: Bearer {token} 格式不对、token 过期、或数据库里 personal_access_tokens 表没对应记录。
实操建议:
- 纯 API 调用(如 Postman、移动端):跳过 session/CSRF,用
Sanctum::createToken()生成 token,客户端必须带Authorization: Bearer <token> - 前端 SPA(Vue/React):走
sanctum/csrf-cookie预请求 + session 登录,后续请求靠 cookie 自动携带,不用手动传 token - 检查
config/sanctum.php的stateful域名配置,本地开发时要包含localhost或127.0.0.1,否则 cookie 不会被发送
Sanctum::user() 总是 null?中间件顺序和路由分组搞错了
常见现象:在控制器里调用 Sanctum::user() 返回 null,但 Auth::user() 却有值;或者反过来。本质是 guard 绑定错位 —— Sanctum::user() 只读当前请求绑定的 sanctum guard,而 Auth::user() 读的是默认 guard(通常是 web)。
实操建议:
- 确保路由明确使用
auth:sanctum中间件,例如:Route::middleware('auth:sanctum')->get('/user', ...) - 不要在未认证的路由里调用
Sanctum::user(),它不会 fallback 到其他 guard - 如果同时支持 cookie 和 token 认证,别混用
Auth::user()和Sanctum::user(),二者来源不同、生命周期不同、权限上下文也不同 - 调试时可用
dd(request()->user(), Auth::guard('sanctum')->user())对比实际取到的用户
生产环境 token 失效太快?别只改 expires_at
Sanctum 的 token 默认永不过期(expires_at = null),但如果你手动设了过期时间,或用了自定义 token 生成逻辑,又没同步清理过期记录,会导致 DB 积累大量失效 token,影响查询性能,甚至触发 MySQL 的 fulltext 索引失效问题。
实操建议:
- 不推荐用
expires_at控制单 token 生命周期,Sanctum 更适合用「按需创建 + 主动撤销」模式 - 用
$user->tokens()->delete()或$user->currentAccessToken()->delete()显式注销 - 定期清理(如 Laravel Task Scheduler):
DB::table('personal_access_tokens')->where('expires_at', 'delete() - 注意:
Sanctum::authenticateSession()是为 SPA 设计的,不适用于无状态 API,别误用
真正麻烦的不是怎么配,而是搞清你到底要 session 还是 token —— 选错模式,后面所有 header、cookie、中间件、token 存储方式都会连锁出错。










