Laravel Sanctum如何支持复合主键模型生成API令牌?
在复合主键的Laravel模型中使用Sanctum令牌的解决方案
Laravel Sanctum默认依赖模型的单一主键关联令牌,复合主键场景下会因getKey()返回数组导致array_key_exists报错,以下是适配复合主键的具体方案:
1. 扩展Sanctum令牌表
首先修改personal_access_tokens表,添加复合主键的第二个字段(这里是tenant_id)来存储完整的关联标识:
// 生成新迁移文件执行,或修改原有Sanctum迁移 Schema::table('personal_access_tokens', function (Blueprint $table) { $table->string('tenant_id')->nullable(); });
2. 修改PersonalAccessToken模型的关联逻辑
在app/Models/PersonalAccessToken.php中,重写tokenable关联方法,让它同时匹配tokenable_id和tenant_id:
public function tokenable() { return $this->morphTo()->where('tenant_id', $this->tenant_id); }
3. 自定义Device模型的令牌创建逻辑
在你的Device模型中,重写createToken和tokens关联方法,确保令牌创建时保存复合主键的两个字段,同时关联查询时匹配完整主键:
use Laravel\Sanctum\HasApiTokens; use Laravel\Sanctum\PersonalAccessToken; use Illuminate\Support\Str; class Device extends Model { use HasApiTokens; // 声明复合主键 protected $primaryKey = ['device_id', 'tenant_id']; public $incrementing = false; /** * 重写令牌创建方法,保存tenant_id */ public function createToken(string $name, array $abilities = ['*']) { $plainTextToken = Str::random(40); $token = $this->tokens()->create([ 'name' => $name, 'token' => hash('sha256', $plainTextToken), 'abilities' => $abilities, 'tenant_id' => $this->tenant_id, ]); return new \Laravel\Sanctum\NewAccessToken($token, $token->getKey().'|'.$plainTextToken); } /** * 重写令牌关联,匹配复合主键 */ public function tokens() { return $this->morphMany(PersonalAccessToken::class, 'tokenable') ->where('tenant_id', $this->tenant_id); } }
4. 验证功能
完成以上修改后,重新运行迁移,然后在控制器中调用$device->createToken('IoT Token')即可正常生成关联复合主键的Sanctum令牌,认证时Sanctum会通过tokenable_id和tenant_id共同匹配到对应的设备。
内容的提问来源于stack exchange,提问作者Ernesto Pareja
相关产品推荐
相关产品推荐

