JWT多用户守卫不生效的核心原因是Laravel守卫配置与中间件未对齐:需显式设driver为jwt、为各守卫配置对应provider和模型、使用jwt.auth等专用中间件、模型实现JWTSubject接口、密码必须bcrypt哈希,且应避免使用已归档的tymon/jwt-auth。

JWT 多用户守卫不生效,核心问题通常不在 JWT 本身,而在于 Laravel 的守卫(Guard)配置与中间件协同机制未对齐。它不是“装了包就自动多守卫”,而是必须显式声明、逐层适配:从 auth 配置、模型契约、路由中间件到异常兜底,缺一不可。
守卫驱动必须显式设为 jwt
默认的 api 守卫用的是 token 驱动,查 personal_access_tokens 表,和 JWT 完全无关。哪怕你用了 tymon/jwt-auth 或 php-open-source-saver/jwt-auth,它也不会自动接管。
- 打开
config/auth.php,定位到'guards' => ['api' => [...]],把'driver' => 'token'改成'driver' => 'jwt' - 若你有多个 JWT 守卫(如
admin、user),每个都要单独配置:'admin' => ['driver' => 'jwt', 'provider' => 'admins'] - 确保对应 provider 的 model 正确指向各自的用户类(如
App\Models\Admin)
中间件必须匹配守卫名称,不能混用
用 auth:api 中间件 ≠ JWT 认证生效。Laravel 8+ 的 auth:xxx 中间件只认你配置里定义的 driver 类型,不认包名或别名。
- 正确写法是
middleware('jwt.auth')(来自Tymon\JWTAuth\Middleware\GetUserFromToken) - 如果你自定义了
admin守卫,且想让它独立工作,需注册对应中间件,例如'jwt.admin' => \App\Http\Middleware\JwtAdminMiddleware::class - 路由中明确指定守卫组合:
Route::middleware(['jwt.auth:admin,user'])->group(...),让中间件按顺序尝试
User 模型必须严格实现 JWTSubject 接口
这是 JWT 能生成/验证 token 的前提。漏掉任一方法,或返回非法值,都会导致 TokenCouldNotBeCreatedException,表现为登录 401 或 Auth::user() 为空。
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
- 在
App\Models\User(及其它用户模型)中引入并实现接口:use Tymon\JWTAuth\Contracts\JWTSubject;+implements JWTSubject -
getJWTIdentifier()必须返回标量(如$this->getKey()),不能是$this->id(可能触发延迟加载或 null) -
getJWTCustomClaims()可返回空数组,但方法体不能缺失;键名不能含点(.)或非字符串类型
密码哈希必须为 bcrypt 格式
JWT 的 attempt() 底层调用 Hash::check(),只认 Laravel 原生 bcrypt。MD5、SHA1、明文或手动拼接的 hash 全部失败,直接返回 false → 401。
- 检查数据库
users.password字段是否以$2y$、$2a$或$2b$开头 - 创建用户必须用
Hash::make('password'),禁用md5()、bcrypt()手动调用 - Seeder 或 tinker 中测试账号务必走标准流程:
User::create(['email' => 'x', 'password' => Hash::make('123')])
别再依赖已归档的 tymon/jwt-auth
该包自 Laravel 8 起已停止维护,PHP 8.1+ 和 Laravel 9/10 兼容性差,常见报错如 Class not found、Service provider missing 等,本质是架构过时,不是配置问题。
- 生产项目建议迁移到
laravel/sanctum:运行composer require laravel/sanctum+php artisan sanctum:install - 登录改用
$user->createToken('api')->plainTextToken,守卫用auth:sanctum - 若必须用标准 JWT(如对接外部系统),轻量方案是
firebase/php-jwt,自己封装签发/验证逻辑,5 分钟可上线,无兼容风险










