Класс RateLimiter
Класс RateLimiter используется для управления ограничениями частоты запросов в приложении Laravel. Он работает на основе кеша и позволяет легко реализовать защиту от чрезмерного количества операций. Класс предоставляет методы для проверки лимитов, регистрации попыток и получения информации о доступных попытках.
Базовое использование
Для использования RateLimiter необходимо получить экземпляр класса через фасад. Основные методы позволяют управлять попытками и проверять лимиты:
<?php
use Illuminate\Support\Facades\RateLimiter;
$key = 'login_attempts:user1';
$maxAttempts = 5;
$decaySeconds = 60;
$res = RateLimiter::attempt(
$key,
$maxAttempts,
function () {
return true;
},
$decaySeconds
);
echo $res ? "true" : "false";
?>
Результат выполнения кода:
"true"
Метод attempt
Метод attempt является основным для выполнения ограниченных операций. Он принимает ключ, максимальное количество попыток, колбэк-функцию и количество секунд для сброса счётчика. Если лимит не превышен, колбэк выполняется и метод возвращает true, иначе возвращается false.
<?php
use Illuminate\Support\Facades\RateLimiter;
$key = 'api_request:user1';
$maxAttempts = 3;
$decaySeconds = 30;
$res = RateLimiter::attempt($key, $maxAttempts, function () {
return true;
}, $decaySeconds);
echo $res ? "true" : "false";
?>
Результат выполнения кода:
"true"
Метод tooManyAttempts
Метод tooManyAttempts проверяет, превышен ли лимит попыток для указанного ключа. Он возвращает true, если количество попыток равно или превышает максимальное значение, и false в противном случае.
<?php
use Illuminate\Support\Facades\RateLimiter;
$key = 'api_request:user1';
$maxAttempts = 3;
$res = RateLimiter::tooManyAttempts($key, $maxAttempts);
echo $res ? "true" : "false";
?>
Результат выполнения кода:
"false"
Метод hit
Метод hit регистрирует попытку выполнения операции для указанного ключа. Он автоматически увеличивает счётчик попыток и устанавливает время истечения. Метод возвращает количество оставшихся попыток.
<?php
use Illuminate\Support\Facades\RateLimiter;
$key = 'api_request:user1';
$decaySeconds = 60;
$res = RateLimiter::hit($key, $decaySeconds);
echo $res;
?>
Результат выполнения кода:
"2"
Метод remaining
Метод remaining возвращает количество оставшихся попыток для указанного ключа. Это позволяет информировать пользователя о том, сколько попыток у него ещё осталось.
<?php
use Illuminate\Support\Facades\RateLimiter;
$key = 'api_request:user1';
$maxAttempts = 5;
$res = RateLimiter::remaining($key, $maxAttempts);
echo $res;
?>
Результат выполнения кода:
"2"
Метод availableIn
Метод availableIn возвращает количество секунд, через которое счётчик попыток будет сброшен и операция станет доступна снова. Это полезно для отображения времени ожидания.
<?php
use Illuminate\Support\Facades\RateLimiter;
$key = 'api_request:user1';
$res = RateLimiter::availableIn($key);
echo $res;
?>
Результат выполнения кода:
"45"
Метод clear
Метод clear удаляет все записи о попытках для указанного ключа. Это позволяет сбросить лимит операций вручную.
<?php
use Illuminate\Support\Facades\RateLimiter;
$key = 'api_request:user1';
$res = RateLimiter::clear($key);
echo $res ? "true" : "false";
?>
Результат выполнения кода:
"true"
Практический пример использования
Рассмотрим практический пример использования класса RateLimiter для ограничения попыток входа в систему:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
class AuthController extends Controller
{
public function login(Request $request)
{
$key = 'login:' . $request->ip();
$maxAttempts = 5;
$decaySeconds = 60;
if (RateLimiter::tooManyAttempts($key, $maxAttempts)) {
$seconds = RateLimiter::availableIn($key);
return response()->json([
'message' => 'Too many login attempts',
'available_in' => $seconds,
], 429);
}
$res = RateLimiter::attempt($key, $maxAttempts, function () use ($request) {
return auth()->attempt($request->only('email', 'password'));
}, $decaySeconds);
if (!$res) {
RateLimiter::hit($key, $decaySeconds);
return response()->json([
'message' => 'Invalid credentials',
'remaining' => RateLimiter::remaining($key, $maxAttempts),
], 401);
}
RateLimiter::clear($key);
return response()->json([
'message' => 'Login successful',
'token' => $request->user()->createToken('auth-token')->plainTextToken,
]);
}
}
?>