Laravel实现多用户JWT认证的关键是为每类用户配置独立guard与provider,并确保中间件、路由、令牌生成均显式指定对应guard名。需在auth.php中定义多个jwt驱动guard(如admin、merchant),各自绑定不同provider和模型;各模型实现JWTSubject接口并注入guard标识;登录时用Auth::guard('admin')->attempt()生成token;路由通过middleware('auth:admin')隔离验证。

在 Laravel 中实现多用户 JWT 令牌(如管理员、普通用户、商家等不同守卫)的关键,是为每类用户配置独立的 guard 和 provider,并确保 JWT 认证中间件能正确识别和验证对应守卫的令牌。Laravel 自身不内置 JWT,通常使用 tymon/jwt-auth(兼容 Laravel 8 及以下)或更现代的替代方案(如 laravel/sanctum 或 spatie/laravel-jwt),本文以主流的 tymon/jwt-auth(v1.0+,适配 Laravel 8/9/10)为例说明核心绑定逻辑。
1. 定义多个守卫与提供器(guards & providers)
在 config/auth.php 中,为不同用户类型添加独立守卫,并指向各自对应的 Eloquent provider:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users', // 默认用户
],
'admin' => [
'driver' => 'jwt',
'provider' => 'admins',
],
'merchant' => [
'driver' => 'jwt',
'provider' => 'merchants',
],
],
<p>'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
],
'merchants' => [
'driver' => 'eloquent',
'model' => App\Models\Merchant::class,
],
],</p>注意:driver 均设为 jwt,表示这些守卫均走 JWT 认证流程;每个 provider 对应不同模型,模型需实现 JWTSubject 接口(见下一步)。
2. 各用户模型实现 JWTSubject 接口
每个用于签发 JWT 的模型(如 User、Admin、Merchant)必须实现 Tymon\JWTAuth\Contracts\JWTSubject 接口,提供唯一标识和自定义声明支持:
- 在模型中引入接口并实现两个方法:
getJWTIdentifier()(返回主键)和getJWTCustomClaims()(返回额外载荷,如'type' => 'admin') - 示例 Admin 模型片段:
use Tymon\JWTAuth\Contracts\JWTSubject;
<p>class Admin extends Authenticatable implements JWTSubject
{
public function getJWTIdentifier()
{
return $this->getKey();
}</p><pre class="brush:php;toolbar:false;">public function getJWTCustomClaims()
{
return [
'type' => 'admin',
'guard' => 'admin'
];
}}
该自定义 claim 可用于后续中间件路由守卫判断,也便于前端区分用户类型。
3. 手动为指定守卫生成 JWT 令牌
不能直接调用 Auth::attempt(),因为它是全局守卫绑定的。需显式指定守卫实例:
- 使用
Auth::guard('admin')获取对应守卫实例 - 调用
attempt()并传入凭证(如 email/password) - 成功后通过
Auth::guard('admin')->setToken(...)或直接Auth::guard('admin')->login($admin)生成 token
示例登录控制器逻辑:
use Illuminate\Support\Facades\Auth;
<p>public function adminLogin(Request $request)
{
$credentials = $request->only('email', 'password');</p><pre class="brush:php;toolbar:false;">if (!$token = Auth::guard('admin')->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => Auth::guard('admin')->factory()->getTTL() * 60,
'user' => Auth::guard('admin')->user()
]);}
同理可实现 merchantLogin()、userLogin() 等方法,各走各自守卫。
4. 路由与中间件按守卫隔离访问
在 routes/api.php 中,为不同用户类型分组路由,并绑定对应守卫中间件:
// 管理员 API
Route::prefix('admin')->middleware('auth:admin')->group(function () {
Route::get('/dashboard', [AdminController::class, 'dashboard']);
});
<p>// 商家 API
Route::prefix('merchant')->middleware('auth:merchant')->group(function () {
Route::get('/profile', [MerchantController::class, 'profile']);
});</p><p>// 普通用户 API(默认 api guard)
Route::middleware('auth:api')->group(function () {
Route::get('/user', [UserController::class, 'show']);
});</p>JWT 中间件会自动读取请求中的 Authorization: Bearer xxx,并根据中间件参数(如 auth:admin)选择对应守卫解析 token —— 此时它会使用 admins provider 查找模型,并校验签名与有效期。
不复杂但容易忽略:务必确认所有模型的 $fillable、数据库字段(如密码加密方式)、以及 JWT_SECRET 已正确生成(php artisan jwt:secret)。多守卫下 token 互不兼容,一个守卫签发的 token 无法被另一个守卫验证,这是安全隔离的基础。











