laravel jwt多表认证关键是为每类用户配置独立guard+provider组合并严格对齐模型、中间件和登录调用:1.在auth.php中新增guard(如admin/merchant)及对应provider;2.各模型实现jwtsubject,getjwtcustomclaims返回guard标识;3.所有auth操作显式指定guard名;4.中间件必须写auth:admin等形式;5.黑名单需按guard切片隔离。

要让 Laravel 的 JWT 认证支持多个用户表(比如 users、admins、merchants),关键不是改一个配置,而是为每类用户建立独立的 guard + provider 组合,并确保模型、中间件、登录调用三者严格对齐。
1. 配置多个 guard 和 provider
在 config/auth.php 中新增对应守卫和提供者:
- 在
'guards'下添加:
'admin' => [
'driver' => 'jwt',
'provider' => 'admins'
],
'merchant' => [
'driver' => 'jwt',
'provider' => 'merchants'
]
- 在
'providers'下添加:
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class
],
'merchants' => [
'driver' => 'eloquent',
'model' => App\Models\Merchant::class
]
2. 模型实现 JWTSubject 并区分上下文
每个模型必须实现 JWTSubject 接口,并在 getJWTCustomClaims() 中注入 guard 标识,用于后续黑名单隔离和 payload 区分:
- Admin.php 示例:
public function getJWTCustomClaims()
{
return ['guard' => 'admin'];
}
- Merchant.php 示例:
public function getJWTCustomClaims()
{
return ['guard' => 'merchant'];
}
同时确保 getJWTIdentifier() 返回主键值(通常直接用 $this->getKey())。
3. 登录与鉴权必须显式指定 guard
不能依赖默认 guard,所有操作需手动传入 guard 名称:
- 登录时用:
Auth::guard('admin')->login($admin),而非Auth::login($admin) - 获取当前用户:
Auth::guard('merchant')->user() - 刷新 token:
Auth::guard('admin')->refresh() - 登出:
Auth::guard('admin')->logout()
否则会走默认 api guard,导致 token 冲突或鉴权失败。
4. 中间件与路由绑定 guard 名
路由定义中,中间件必须带 guard 参数:
- 正确写法:
middleware('auth:admin') - 错误写法:
middleware('auth:api')或仅middleware('auth')
可为不同前缀路由分组设置对应中间件:
Route::prefix('admin')->middleware('auth:admin')->group(function () {
Route::get('/dashboard', [AdminController::class, 'index']);
});
5. 黑名单与缓存隔离(防 token 误删)
tymon/jwt-auth 默认黑名单不区分 guard,需手动切片。推荐做法:
- 重写
JWTBlacklist::add()方法,在 cache key 或数据库字段中拼入$payload['guard'] - 例如缓存 key 改为:
blacklist_{$guard}_{$jti} - 若使用数据库黑名单表,增加
guard字段并建联合索引
否则 Auth::guard('admin')->logout() 可能清掉 user 的 token,造成越权或会话中断。











