jwt多用户注销需服务端黑名单机制并按guard隔离,避免越权;各模型在getjwtcustomclaims中注入guard标识,重写add方法使redis键含guard前缀,注销与校验均须指定guard,登录/刷新/中间件均需显式声明guard。

JWT 多用户注销时,不能只删前端 token,必须让服务端主动让 token 失效——核心就是用黑名单(Blacklist)机制,且要区分不同用户类型(如 user、admin、merchant),避免互相干扰。
黑名单必须按 guard 隔离
tymon/jwt-auth 默认的黑名单是全局单例,不感知 guard 上下文。如果 users 和 admins 共用一个黑名单,admin 调用 logout 就可能误删 user 的 token,或刷新时 payload 混用导致越权。
- 每个模型(User、Admin 等)在
getJWTCustomClaims()中显式注入 guard 标识:'guard' => 'admin' - 重写
JWTBlacklist::add()方法,把$payload['guard']拼进 Redis key 或数据库字段,例如:jwt:blacklist:admin:abc123 - 校验 token 前,先查对应 guard 前缀的黑名单项,而不是无差别匹配 jti
注销流程要走对 guard
调用 logout 必须明确指定 guard,否则默认走 api 或 web,容易签发/销毁错表。
- 登录时用
Auth::guard('admin')->login($admin),不是Auth::login($admin) - 退出时用
Auth::guard('admin')->logout(),它会自动把当前 token 的 jti + guard 前缀加入黑名单 - 中间件也得带 guard 名:
middleware('auth:admin'),不能只写auth:api
客户端清理 + 服务端失效双保险
前端清 token 是体验必需,但不是安全底线;服务端黑名单才是关键防线。
- 前端登出后立即移除 localStorage 或 Cookie 中的 token,并跳转登录页
- 服务端 /logout 接口返回成功前,确保
Auth::guard('admin')->logout()已执行完毕 - 配合 jti 唯一标识 + Redis TTL(设为和 token 相同过期时间),避免黑名单无限膨胀
别踩这些坑
多 guard 场景下,配置和代码稍有疏漏就会导致鉴权失效或越权。
- config/auth.php 中新增 guard 后,provider 必须一一对应,model 类路径不能写错
- 每个 model 都要实现
JWTSubject,getJWTIdentifier()返回主键,不可为空 - 不要在同一个项目里混用 tymon/jwt-auth 和 laravel/sanctum,两者 token 生命周期管理逻辑冲突
- 刷新 token 也要指定 guard:
Auth::guard('admin')->refresh(),否则可能返回 user 的新 token











