AgentAuthService.php 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. <?php
  2. namespace App\Services\Agent;
  3. use App\Models\Agent\Agent;
  4. use App\Models\Agent\AgentLoginLog;
  5. use App\Models\Agent\AgentToken;
  6. use Illuminate\Http\Request;
  7. use Illuminate\Support\Facades\DB;
  8. use Illuminate\Support\Facades\Hash;
  9. class AgentAuthService
  10. {
  11. public function __construct(private AgentContextService $context)
  12. {
  13. }
  14. public function login(string $username, string $password, Request $request): array
  15. {
  16. $agent = Agent::query()->where('username', $username)->first();
  17. if (!$agent || !Hash::check($password, (string) $agent->password)) {
  18. throw new \InvalidArgumentException('代理账号或密码错误');
  19. }
  20. if ((int) $agent->status !== Agent::STATUS_ENABLED) {
  21. throw new \InvalidArgumentException('代理账号已禁用');
  22. }
  23. return DB::transaction(function () use ($agent, $password, $request): array {
  24. $lockedAgent = Agent::query()->lockForUpdate()->findOrFail($agent->id);
  25. if (!Hash::check($password, (string) $lockedAgent->password)) {
  26. throw new \InvalidArgumentException('代理账号或密码错误');
  27. }
  28. if ((int) $lockedAgent->status !== Agent::STATUS_ENABLED) {
  29. throw new \InvalidArgumentException('代理账号已禁用');
  30. }
  31. $plainToken = bin2hex(random_bytes(32));
  32. $device = $this->context->device($request);
  33. $location = $this->context->location($request);
  34. $now = now();
  35. AgentToken::query()->where('agent_id', $lockedAgent->id)->delete();
  36. AgentToken::query()->create([
  37. 'agent_id' => $lockedAgent->id,
  38. 'token_hash' => hash('sha256', $plainToken),
  39. 'expires_at' => $now->copy()->addDays(config('agent.token_ttl_days', 7)),
  40. 'last_used_at' => $now,
  41. 'ip' => $request->ip() ?: '',
  42. 'device' => $device,
  43. ]);
  44. AgentLoginLog::query()->create(array_merge($location, [
  45. 'agent_id' => $lockedAgent->id,
  46. 'username' => $lockedAgent->username,
  47. 'domain' => $this->context->domain($request),
  48. 'ip' => $request->ip() ?: '',
  49. 'device' => $device,
  50. 'user_agent' => mb_substr((string) $request->userAgent(), 0, 500),
  51. 'login_at' => $now,
  52. ]));
  53. $lockedAgent->last_login_at = $now;
  54. $lockedAgent->last_login_ip = $request->ip() ?: '';
  55. $lockedAgent->save();
  56. return [
  57. 'token' => $plainToken,
  58. 'token_type' => 'Bearer',
  59. 'expires_at' => $now->copy()->addDays(config('agent.token_ttl_days', 7))->toDateTimeString(),
  60. ];
  61. });
  62. }
  63. public function logout(AgentToken $token): void
  64. {
  65. $token->delete();
  66. }
  67. }