'json', 'last_used_at' => 'datetime', 'expires_at' => 'datetime', 'created_at' => 'datetime', 'updated_at' => 'datetime', ]; /** * 隐藏的属性 * * @var array */ protected $hidden = [ 'key_secret', ]; /** * 状态常量 */ const STATUS_ACTIVE = 'ACTIVE'; const STATUS_INACTIVE = 'INACTIVE'; const STATUS_EXPIRED = 'EXPIRED'; const STATUS_REVOKED = 'REVOKED'; /** * 关联应用模型 * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function app() { return $this->belongsTo(OpenApiApp::class, 'app_id', 'app_id'); } /** * 生成新的API密钥 * * @param string $appId * @param array $data * @return static */ public static function generate(string $appId, array $data = []): self { $keyId = 'ak_' . Str::random(32); $keySecret = 'sk_' . Str::random(64); return self::create([ 'app_id' => $appId, 'key_id' => $keyId, 'key_secret' => hash('sha256', $keySecret), // 加密存储 'name' => $data['name'] ?? 'Default Key', 'description' => $data['description'] ?? '', 'scopes' => $data['scopes'] ?? [], 'status' => self::STATUS_ACTIVE, 'expires_at' => $data['expires_at'] ?? null, ]); } /** * 验证密钥 * * @param string $keyId * @param string $keySecret * @return static|null */ public static function validateKey(string $keyId, string $keySecret): ?self { $key = self::where('key_id', $keyId) ->where('status', self::STATUS_ACTIVE) ->first(); if (!$key) { return null; } // 验证密钥 if (!hash_equals($key->key_secret, hash('sha256', $keySecret))) { return null; } // 检查是否过期 if ($key->expires_at && $key->expires_at->isPast()) { $key->update(['status' => self::STATUS_EXPIRED]); return null; } // 更新最后使用时间 $key->update(['last_used_at' => now()]); return $key; } /** * 撤销密钥 * * @return bool */ public function revoke(): bool { return $this->update(['status' => self::STATUS_REVOKED]); } /** * 激活密钥 * * @return bool */ public function activate(): bool { return $this->update(['status' => self::STATUS_ACTIVE]); } /** * 停用密钥 * * @return bool */ public function deactivate(): bool { return $this->update(['status' => self::STATUS_INACTIVE]); } /** * 检查密钥是否有效 * * @return bool */ public function isValid(): bool { if ($this->status !== self::STATUS_ACTIVE) { return false; } if ($this->expires_at && $this->expires_at->isPast()) { return false; } return true; } /** * 检查是否有指定权限 * * @param string $scope * @return bool */ public function hasScope(string $scope): bool { $scopes = $this->scopes ?? []; // 检查是否有管理员权限 if (in_array('ADMIN', $scopes)) { return true; } return in_array($scope, $scopes); } /** * 获取状态标签 * * @return string */ public function getStatusLabelAttribute(): string { return match($this->status) { self::STATUS_ACTIVE => '激活', self::STATUS_INACTIVE => '停用', self::STATUS_EXPIRED => '已过期', self::STATUS_REVOKED => '已撤销', default => '未知', }; } /** * 获取状态颜色 * * @return string */ public function getStatusColorAttribute(): string { return match($this->status) { self::STATUS_ACTIVE => 'success', self::STATUS_INACTIVE => 'warning', self::STATUS_EXPIRED => 'danger', self::STATUS_REVOKED => 'secondary', default => 'secondary', }; } /** * 按应用ID查询 * * @param \Illuminate\Database\Eloquent\Builder $query * @param string $appId * @return \Illuminate\Database\Eloquent\Builder */ public function scopeByApp($query, string $appId) { return $query->where('app_id', $appId); } /** * 只查询有效的密钥 * * @param \Illuminate\Database\Eloquent\Builder $query * @return \Illuminate\Database\Eloquent\Builder */ public function scopeValid($query) { return $query->where('status', self::STATUS_ACTIVE) ->where(function($q) { $q->whereNull('expires_at') ->orWhere('expires_at', '>', now()); }); } /** * 只查询过期的密钥 * * @param \Illuminate\Database\Eloquent\Builder $query * @return \Illuminate\Database\Eloquent\Builder */ public function scopeExpired($query) { return $query->where('expires_at', '<', now()); } }