多守卫jwt路由鉴权需guard、provider、中间件、路由四者协同:在auth.php定义admin-api/user-api/guest-api三类守卫,创建可传参的jwtguard中间件,路由按前缀分组绑定对应中间件,登录接口按守卫签发token并确保payload与provider一致。

多守卫 JWT 路由鉴权的核心,是让不同来源的请求(比如管理员、普通用户、访客)走各自独立的认证通道,并在路由层精准绑定对应中间件。它不是简单地“加个 middleware”,而是 Guard、Provider、中间件、路由四者协同的结果。
明确多守卫结构并配置 guard
先在 config/auth.php 中定义多个 API 守卫,每个对应一类用户来源和验证逻辑:
-
admin-api:使用 JWT 驱动,provider 指向
admins表,用于后台管理接口 -
user-api:同样用 JWT 驱动,但 provider 指向
users表,用于 APP 或前端用户接口 -
guest-api:可配置为自定义驱动,支持解析含
"is_guest": true声明的 Token,不查数据库
关键点:每个 guard 的 'driver' => 'jwt'(或 'sanctum')必须匹配你实际使用的认证机制;provider 必须正确定义模型与表,否则 Auth::guard('xxx')->user() 始终为空。
注册专用中间件并传参识别守卫
不要复用 auth:api,而是创建可指定守卫的中间件:
- 运行
php artisan make:middleware JwtGuard - 在
handle()方法中接收守卫名参数:public function handle($request, Closure $next, $guard = 'api') - 手动调用守卫验证:
if (!Auth::guard($guard)->check()) { abort(401); } - 注册别名如
'jwt.admin' => \App\Http\Middleware\JwtGuard::class到Kernel.php
这样就能在路由中显式声明守卫:->middleware('jwt.admin'),避免守卫混淆导致的 Auth::user() === null。
按守卫分组定义路由并隔离中间件
路由不能混用,必须物理隔离:
- 管理员接口统一进
routes/api.php的子组:Route::prefix('admin')->middleware('jwt.admin')->group(...) - 用户接口走另一组:
Route::prefix('v1')->middleware('jwt.user')->group(...) - 访客接口单独处理,可加额外校验(如检查 payload 是否含
is_guest)
特别注意:API 路由组默认不含 StartSession 中间件,这点比 web 组更干净;但若误把 auth:api 放在 web 组里,会因 session 冲突导致 JWT 解析失败。
Token 签发与响应需匹配守卫上下文
登录接口必须按守卫分别实现:
- 管理员登录返回的 Token,应由
Auth::guard('admin-api')->login($admin)生成(tymon/jwt-auth)或$admin->createToken('admin', ['admin'])->plainTextToken(Sanctum) - 用户登录同理,确保 Token 的
sub和签发逻辑与对应 guard 的 provider 一致 - 访客 Token 若为手动签发(如用
firebase/php-jwt),payload 中需包含可被守卫识别的字段(如"guard": "guest-api"),并在中间件中提取判断
客户端后续请求必须带正确 Header:Authorization: Bearer xxx,且后端中间件才能按预设守卫完成解析与授权。











