where('username', $username)->first(); if (!$agent || !Hash::check($password, (string) $agent->password)) { throw new \InvalidArgumentException('代理账号或密码错误'); } if ((int) $agent->status !== Agent::STATUS_ENABLED) { throw new \InvalidArgumentException('代理账号已禁用'); } return DB::transaction(function () use ($agent, $password, $request): array { $lockedAgent = Agent::query()->lockForUpdate()->findOrFail($agent->id); if (!Hash::check($password, (string) $lockedAgent->password)) { throw new \InvalidArgumentException('代理账号或密码错误'); } if ((int) $lockedAgent->status !== Agent::STATUS_ENABLED) { throw new \InvalidArgumentException('代理账号已禁用'); } $plainToken = bin2hex(random_bytes(32)); $device = $this->context->device($request); $location = $this->context->location($request); $now = now(); AgentToken::query()->where('agent_id', $lockedAgent->id)->delete(); AgentToken::query()->create([ 'agent_id' => $lockedAgent->id, 'token_hash' => hash('sha256', $plainToken), 'expires_at' => $now->copy()->addDays(config('agent.token_ttl_days', 7)), 'last_used_at' => $now, 'ip' => $request->ip() ?: '', 'device' => $device, ]); AgentLoginLog::query()->create(array_merge($location, [ 'agent_id' => $lockedAgent->id, 'username' => $lockedAgent->username, 'domain' => $this->context->domain($request), 'ip' => $request->ip() ?: '', 'device' => $device, 'user_agent' => mb_substr((string) $request->userAgent(), 0, 500), 'login_at' => $now, ])); $lockedAgent->last_login_at = $now; $lockedAgent->last_login_ip = $request->ip() ?: ''; $lockedAgent->save(); return [ 'token' => $plainToken, 'token_type' => 'Bearer', 'expires_at' => $now->copy()->addDays(config('agent.token_ttl_days', 7))->toDateTimeString(), ]; }); } public function logout(AgentToken $token): void { $token->delete(); } }