You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:

  1. 生成密码授权客户端:
    php artisan passport:client --password
    
  2. 创建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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:05:43