Laravel实现多模型JWT身份核验需配置多个守卫及对应provider,控制器中显式调用Auth::guard('xxx')->user()或通过路由中间件自动绑定,登录接口须按模型分别调用attempt()签发token。

Laravel 中实现多模型 JWT 身份核验,关键不在“能不能”,而在于守卫(Guard)如何精准绑定对应模型、驱动如何正确解析 token 并定位用户实体。控制器里不能硬写 Auth::user() 就完事——它默认走的是 config/auth.php 里 defaults.guard 指定的守卫,而多模型场景下,你往往需要按请求动态切换守卫,或为不同模型预设独立守卫。
一、先配好多个守卫,各管各的模型
在 config/auth.php 的 'guards' 数组中,为每个用户模型定义专属守卫。例如:
'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users', // 对应 users 表 + App\Models\User
],
'admin_api' => [
'driver' => 'jwt',
'provider' => 'admins', // 对应 admins 表 + App\Models\Admin
],
'seller_api' => [
'driver' => 'jwt',
'provider' => 'sellers', // 对应 sellers 表 + App\Models\Seller
],
],对应地,在 'providers' 中声明这些提供者,确保模型路径、主键、认证字段(如 email)都准确:
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
],
'sellers' => [
'driver' => 'eloquent',
'model' => App\Models\Seller::class,
],
],⚠️ 注意:所有模型必须支持 JWTSubject(若用
tymon/jwt-auth),或至少实现getAuthIdentifier()和getAuthPassword()(若手写验证逻辑)。
二、控制器内手动调用指定守卫获取用户
不要依赖全局 Auth::user(),而是显式调用守卫实例:
use Illuminate\Support\Facades\Auth;
// 获取 admin 用户(使用 admin_api 守卫)
$admin = Auth::guard('admin_api')->user();
// 获取 seller 用户
$seller = Auth::guard('seller_api')->user();
// 验证是否已通过该守卫认证
if (!Auth::guard('admin_api')->check()) {
return response()->json(['message' => 'Admin not authenticated'], 401);
}也可以在构造函数或中间件中提前绑定,避免重复写 guard('xxx'):
public function __construct()
{
$this->middleware(function ($request, $next) {
if ($request->is('api/admin/*')) {
Auth::shouldUse('admin_api');
} elseif ($request->is('api/seller/*')) {
Auth::shouldUse('seller_api');
}
return $next($request);
});
}之后在方法内直接用 Auth::user() 即可返回对应模型实例。
三、路由分组 + 中间件自动匹配守卫
更推荐的做法是按前缀路由绑定守卫,配合自定义中间件或 Laravel 原生 auth:xxx 语法:
Route::prefix('admin')->middleware('auth:admin_api')->group(function () {
Route::get('/dashboard', [AdminController::class, 'dashboard']);
});
Route::prefix('seller')->middleware('auth:seller_api')->group(function () {
Route::get('/products', [SellerController::class, 'index']);
});此时中间件 auth:seller_api 会自动使用 seller_api 守卫校验 token,并把 Auth::user() 绑定到 Seller 模型。
四、登录接口要区分模型签发 token
不同模型的登录接口不能共用一套 attempt(),需分别调用对应守卫的 attempt() 方法:
// Admin 登录
public function adminLogin(Request $request)
{
$credentials = $request->only('email', 'password');
if (!$token = Auth::guard('admin_api')->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return response()->json(compact('token'));
}
// Seller 登录
public function sellerLogin(Request $request)
{
$credentials = $request->only('phone', 'password'); // 可能用 phone 而非 email
if (!$token = Auth::guard('seller_api')->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return response()->json(compact('token'));
}✅ 提示:
attempt()是否成功,取决于该守卫配置的provider模型能否用传入字段查到有效用户,并且密码校验通过。
不复杂但容易忽略


















