'boolean', 'first_login_at' => 'datetime', 'last_login_at' => 'datetime', 'trusted_at' => 'datetime', ]; /** * 用户关联 */ public function user(): BelongsTo { return $this->belongsTo(User::class); } /** * 判断是否授信 */ public function isTrusted(): bool { return $this->is_trusted; } /** * 授信 */ public function trust(): void { $this->update([ 'is_trusted' => true, 'trusted_at' => now(), ]); } /** * 取消授信 */ public function revoke(): void { $this->update([ 'is_trusted' => false, 'trusted_at' => null, ]); } /** * 更新登录信息 */ public function recordLogin(): void { if (!$this->first_login_at) { $this->update(['first_login_at' => now()]); } $this->update(['last_login_at' => now()]); } /** * 通过设备哈希查找 */ public static function findByHash(int $userId, string $hash): ?self { return static::where('user_id', $userId) ->where('device_hash', $hash) ->first(); } /** * 生成设备哈希 */ public static function generateHash(string $userAgent, string $ip): string { return hash('sha256', $userAgent . $ip . config('app.key')); } /** * 解析设备信息 */ public static function parseDeviceInfo(string $userAgent): array { $deviceType = 'desktop'; $os = 'Unknown'; $browser = 'Unknown'; // 检测设备类型 if (preg_match('/mobile|android|iphone|ipad|ipod/i', $userAgent)) { if (preg_match('/ipad/i', $userAgent)) { $deviceType = 'tablet'; } else { $deviceType = 'mobile'; } } // 检测操作系统 if (preg_match('/windows nt 10/i', $userAgent)) { $os = 'Windows 10'; } elseif (preg_match('/windows nt 6.3/i', $userAgent)) { $os = 'Windows 8.1'; } elseif (preg_match('/mac os x/i', $userAgent)) { $os = 'macOS'; } elseif (preg_match('/linux/i', $userAgent)) { $os = 'Linux'; } elseif (preg_match('/android/i', $userAgent)) { $os = 'Android'; } elseif (preg_match('/iphone|ipad|ipod/i', $userAgent)) { $os = 'iOS'; } // 检测浏览器 if (preg_match('/edg/i', $userAgent)) { $browser = 'Edge'; } elseif (preg_match('/chrome/i', $userAgent)) { $browser = 'Chrome'; } elseif (preg_match('/firefox/i', $userAgent)) { $browser = 'Firefox'; } elseif (preg_match('/safari/i', $userAgent)) { $browser = 'Safari'; } elseif (preg_match('/ie|trident/i', $userAgent)) { $browser = 'IE'; } return [ 'device_type' => $deviceType, 'os' => $os, 'browser' => $browser, ]; } }