| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- <?php
- namespace App\Module\OpenAPI\Models;
- use UCore\ModelCore;
- use Illuminate\Support\Str;
- /**
- * OpenAPI密钥模型
- *
- * 管理API密钥的生成、验证和生命周期
- */
- class OpenApiKey extends ModelCore
- {
- /**
- * 数据表名
- *
- * @var string
- */
- protected $table = 'openapi_keys';
- /**
- * 可批量赋值的属性
- *
- * @var array
- */
- protected $fillable = [
- 'app_id',
- 'key_id',
- 'key_secret',
- 'name',
- 'description',
- 'scopes',
- 'status',
- 'last_used_at',
- 'expires_at',
- 'created_at',
- 'updated_at',
- ];
- /**
- * 属性类型转换
- *
- * @var array
- */
- protected $casts = [
- 'scopes' => '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());
- }
- }
|