如何让Laravel Sanctum仅校验归属指定模型的Token
结论
该需求完全可以实现,无需修改Sanctum核心代码,用官方提供的扩展能力即可完成。
Sanctum默认的personal_access_tokens表本身就通过tokenable_type做多态关联区分令牌所属模型,你只需要给令牌查询加上固定的类型过滤条件,就能让鉴权流程只识别归属指定模型(比如App\Models\Group)的令牌。
具体实现方案
最稳定的实现方式是自定义PersonalAccessToken模型,通过全局作用域强制加查询条件,步骤如下:
- 新建自定义的PersonalAccessToken模型,继承Sanctum自带的基类,在启动方法中加全局作用域,限定只查询目标模型的令牌:
<?php namespace App\Models; use Laravel\Sanctum\PersonalAccessToken as BaseToken; use Illuminate\Database\Eloquent\Builder; class PersonalAccessToken extends BaseToken { protected static function booted() { static::addGlobalScope('limit_token_owner', function (Builder $query) { // 这里替换成你要限定的模型类即可,当前示例为仅识别Group模型的令牌 $query->where('tokenable_type', \App\Models\Group::class); }); } }
- 在服务提供者中注册自定义模型,替换Sanctum默认的模型实现。打开
app/Providers/AppServiceProvider.php,在boot方法中加入以下代码:
use Laravel\Sanctum\Sanctum; use App\Models\PersonalAccessToken; public function boot() { Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class); // 其他原有启动逻辑保持不变 }
配置完成后,所有Sanctum的鉴权查询都会自动带上tokenable_type的过滤条件,属于App\Models\User的令牌即使明文、哈希值匹配,也会因为查不到对应记录直接鉴权失败,完全符合需求。
如果你的场景是不同路由需要分别校验不同模型的令牌,不需要全局限制,可以选择写一个校验中间件,在Sanctum解析出令牌后额外判断所属模型,不符合就返回401即可,逻辑更灵活。示例中间件核心逻辑:
public function handle($request, Closure $next) { $token = $request->user()?->currentAccessToken(); if (!$token || $token->tokenable_type !== \App\Models\Group::class) { abort(401); } return $next($request); }
把这个中间件绑定到对应路由上就能实现局部范围的令牌类型校验。
内容的提问来源于stack exchange,提问作者KordDEM
相关产品推荐
相关产品推荐

