*/ public function rules(): array { return [ 'email' => ['required', 'string', 'email'], 'password' => ['required', 'string'], ]; } /** * Попытка аутентификации с проверкой ограничения скорости и блокировки. */ public function authenticate(): void { $this->ensureIsNotRateLimited(); if (! Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) { RateLimiter::hit($this->throttleKey(), $this->decaySeconds()); throw ValidationException::withMessages([ 'email' => __('auth.failed'), ]); } RateLimiter::clear($this->throttleKey()); } /** * Проверка лимита неудачных попыток (ИАФ.6). */ public function ensureIsNotRateLimited(): void { $maxAttempts = (int) config('security.lockout.max_attempts'); if (! RateLimiter::tooManyAttempts($this->throttleKey(), $maxAttempts)) { return; } event(new Lockout($this)); $seconds = RateLimiter::availableIn($this->throttleKey()); throw ValidationException::withMessages([ 'email' => __('auth.throttle', [ 'seconds' => $seconds, 'minutes' => ceil($seconds / 60), ]), ]); } public function throttleKey(): string { return Str::transliterate(Str::lower($this->string('email')).'|'.$this->ip()); } private function decaySeconds(): int { return (int) config('security.lockout.decay_minutes') * 60; } }