Laravel Passport自定义守卫失效:多用户表认证异常排查
解决Laravel Passport多用户表自定义守卫失效问题
嘿,我之前踩过Passport多用户认证的坑,结合你的情况给你拆解一下问题和解决方案:
1. 先确认config/auth.php配置是否正确
这是基础中的基础,一定要确保守卫和用户提供者对应正确:
// config/auth.php return [ 'defaults' => [ 'guard' => 'web', 'passwords' => 'users', ], 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'admin' => [ 'driver' => 'passport', // 指定Passport驱动 'provider' => 'admins', // 对应下面的admins提供者 ], ], 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\User::class, ], 'admins' => [ 'driver' => 'eloquent', 'model' => App\Models\Admin::class, // 你的Admin模型路径 ], ], ];
2. 给Admin模型添加Passport必要的Trait
Passport需要模型实现HasApiTokens才能生成和管理token,别漏了:
// app/Models/Admin.php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Notifications\Notifiable; use Laravel\Passport\HasApiTokens; class Admin extends Model { use HasApiTokens, Notifiable; // 其他模型代码... protected $fillable = ['name', 'email', 'password']; protected $hidden = ['password', 'remember_token']; }
3. 关键:Passport守卫的attempt方法不是用来验证用户名密码的!
你提到的Auth::guard('admin')->attempt(...)失效,核心原因是Passport的TokenGuard(也就是passport驱动的守卫)的attempt方法逻辑和session驱动完全不同:
- Session守卫的
attempt:验证用户名密码,通过后创建会话 - Passport的TokenGuard的
attempt:检查当前请求中是否携带有效的Bearer Token,而不是验证用户名密码
如果想实现Admin用户通过用户名密码获取Token,你需要换一种方式:
方案A:自定义登录逻辑(简单直接)
直接验证Admin的账号密码,通过后生成Token:
use App\Models\Admin; use Illuminate\Support\Facades\Hash; // 示例登录逻辑 $admin = Admin::where('email', $request->email)->first(); if ($admin && Hash::check($request->password, $admin->password)) { // 创建并返回Token $tokenResult = $admin->createToken('Admin Access Token'); $token = $tokenResult->accessToken; return response()->json([ 'access_token' => $token, 'token_type' => 'Bearer', ]); } return response()->json(['error' => 'Unauthorized'], 401);
方案B:使用Passport密码授权模式(更规范)
如果想遵循Passport的标准流程,可以配置密码授权客户端,让Admin用户通过密码授权获取Token:
- 生成密码授权客户端:
php artisan passport:client --password - 创建Admin的登录路由,调用Passport的密码授权逻辑:
Route::post('admin/login', function (Request $request) { $request->validate([ 'email' => 'required|email', 'password' => 'required', ]); $admin = Admin::where('email', $request->email)->first(); if (!$admin || !Hash::check($request->password, $admin->password)) { return response()->json(['error' => 'Invalid credentials'], 401); } // 使用Passport密码授权生成Token $client = DB::table('oauth_clients')->where('password_client', true)->first(); $request->request->add([ 'grant_type' => 'password', 'client_id' => $client->id, 'client_secret' => $client->secret, 'username' => $request->email, 'password' => $request->password, 'scope' => '', ]); $proxy = Request::create( '/oauth/token', 'POST' ); return Route::dispatch($proxy); });
4. 验证自定义守卫是否生效
当Admin用户拿到Token后,在API请求中携带Authorization: Bearer {token},就可以通过Auth::guard('admin')->user()获取当前登录的Admin用户了:
// 在API控制器中 public function profile() { $admin = Auth::guard('admin')->user(); return response()->json($admin); }
常见排查点
- 确保Passport已经正确安装并执行了迁移:
php artisan passport:install - 检查Admin模型的密码是否用
Hash::make()加密存储 - 确认路由是否在
api中间件组下(或者使用auth:admin中间件)
内容的提问来源于stack exchange,提问作者pra izz
相关产品推荐
相关产品推荐

