Laravel Passport中如何用UUID作为sub声明值(不改主键及迁移)
解决Laravel Passport JWT中用UUID替换主键作为
sub声明的问题 要在不修改用户模型主键、不改动oauth_access_tokens和oauth_auth_codes表迁移的前提下,让Passport生成的JWT用users表的subject_id(UUID字段)作为sub声明,只需通过自定义AccessToken模型并替换默认实现即可,步骤如下:
1. 创建自定义AccessToken模型
新建App\Models\AccessToken类,实现AccessTokenInterface并继承Passport原生的AccessToken模型,重写与JWT声明相关的方法:
<?php namespace App\Models; use Laravel\Passport\AccessToken as PassportAccessToken; use Laravel\Passport\Contracts\AccessTokenInterface; class AccessToken extends PassportAccessToken implements AccessTokenInterface { /** * 重写获取JWT subject的方法 * 返回用户的UUID字段(subject_id)而非主键id */ public function getSubject(): string { return $this->user->subject_id; } /** * 重写JWT生成逻辑(原Trait中为私有方法,无法直接复用) */ public function convertToJWT(): string { return \Firebase\JWT\JWT::encode( $this->getJWTClaims(), $this->getPrivateKey(), 'RS256' ); } /** * 构建JWT的所有声明字段 */ protected function getJWTClaims(): array { return [ 'iss' => url('/'), 'sub' => $this->getSubject(), 'aud' => $this->getAudience(), 'iat' => $this->getIssueTime(), 'exp' => $this->getExpirationTime(), 'jti' => $this->getJti(), 'scopes' => $this->scopes(), ]; } }
2. 配置Passport使用自定义模型
在App\Providers\AuthServiceProvider的boot方法中,指定Passport使用我们的自定义AccessToken模型:
<?php namespace App\Providers; use App\Models\AccessToken; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use Laravel\Passport\Passport; class AuthServiceProvider extends ServiceProvider { protected $policies = [ // 你的策略配置 ]; public function boot(): void { $this->registerPolicies(); Passport::routes(); // 替换为自定义AccessToken模型 Passport::useAccessTokenModel(AccessToken::class); } }
3. 确保User模型可访问subject_id字段
在App\Models\User中,确保subject_id字段在$fillable中(或未被$hidden隐藏,不影响关联访问即可):
protected $fillable = [ 'name', 'email', 'password', 'subject_id', ];
原理说明
- 自定义模型实现了
AccessTokenInterface,重写getSubject直接返回用户的UUID字段,替代原生的主键id - 由于原生
AccessTokenTrait中生成JWT的方法为私有,我们重新实现了convertToJWT和getJWTClaims逻辑,确保JWT生成时使用新的sub值 - 此方案不会改动Passport的底层关联逻辑:
oauth_access_tokens表的user_id仍存储用户主键,令牌验证时Passport依然通过该字段关联用户,仅JWT的sub声明替换为UUID,避免暴露主键
内容的提问来源于stack exchange,提问作者shineability
相关产品推荐
相关产品推荐

