Limitador de tasa
El limitador de tasa de webman admite limitación de tasa a través de anotaciones.
Admite controladores de apcu, redis y memoria.
Dirección del código fuente
https://github.com/webman-php/rate-limiter
Instalación
composer require webman/rate-limiter
Uso
<?php
namespace app\controller;
use RuntimeException;
use Webman\RateLimiter\Annotation\RateLimiter;
class UserController
{
#[RateLimiter(limit: 10)]
public function index(): string
{
// Por defecto, la limitación se basa en la IP, y el tiempo unitario predeterminado es 1 segundo
return 'Máximo 10 solicitudes por segundo por IP';
}
#[RateLimiter(limit: 100, ttl: 60, key: RateLimiter::UID)]
public function search(): string
{
// key: RateLimiter::UID, se limita por ID de usuario, se requiere que session('user.id') no esté vacío
return 'Máximo 100 búsquedas por usuario cada 60 segundos';
}
#[RateLimiter(limit: 1, ttl: 60, key: RateLimiter::SID, message: 'Cada persona solo puede enviar 1 correo electrónico por minuto')]
public function sendMail(): string
{
// key: RateLimiter::SID, se limita por session_id
return 'Correo enviado con éxito';
}
#[RateLimiter(limit: 100, ttl: 24*60*60, key: 'coupon', message: 'Las cupones de hoy ya se han agotado, por favor vuelva mañana')]
#[RateLimiter(limit: 1, ttl: 24*60*60, key: RateLimiter::UID, message: 'Cada usuario solo puede canjear un cupón por día')]
public function coupon(): string
{
// key: 'coupon', aquí coupon es una clave personalizada, es decir, se limita globalmente por la clave coupon, máximo 100 cupones por día
// Al mismo tiempo, se limita por ID de usuario, cada usuario solo puede canjear un cupón por día
return 'Cupón enviado con éxito';
}
#[RateLimiter(limit: 5, ttl: 24*60*60, key: [UserController::class, 'getMobile'], message: 'Cada número de teléfono puede recibir un máximo de 5 mensajes de texto al día')]
public function sendSms2(): string
{
// Cuando la clave es una variable, se puede utilizar la forma [clase, método estático] para obtener la clave, por ejemplo, [UserController::class, 'getMobile'] llamará al método getMobile() de UserController y usará su valor de retorno como clave
return 'Mensaje de texto enviado con éxito';
}
/**
* Clave personalizada, obtener número de teléfono, debe ser un método estático
* @return string
*/
public static function getMobile(): string
{
return request()->get('mobile');
}
#[RateLimiter(limit: 1, ttl: 10, key: RateLimiter::IP, message: 'Frecuencia limitada', exception: RuntimeException::class)]
public function testException(): string
{
// La excepción predeterminada cuando se supera el límite es Webman\RateLimiter\RateLimitException, se puede cambiar a través del parámetro exception
return 'ok';
}
}
Descripción
- El intervalo de tiempo predeterminado es de 1 segundo
- Se puede establecer el intervalo de tiempo a través de ttl, por ejemplo,
ttl:60
equivale a 60 segundos - La dimensión de limitación predeterminada es la limitación por IP (por defecto
127.0.0.1
no tiene límite, consulte la sección de configuración a continuación) - Limitación incorporada por IP, limitación por UID (se requiere que
session('user.id')
no esté vacío) y limitación por SID (limitación segúnsession_id
) - Si se usa un proxy nginx, al limitar por IP se debe pasar el encabezado
X-Forwarded-For
, consulte proxy de nginx - Al superar el límite, se activará la excepción
Webman\RateLimiter\RateLimitException
, se puede personalizar la clase de excepción a través deexception:xx
- Cuando se activa la excepción por exceder el límite, el mensaje de error predeterminado es
Too Many Requests
, se puede personalizar el mensaje de error a través demessage:xx
- El mensaje de error predeterminado también se puede modificar a través de traducción multilenguaje, en Linux consulte los siguientes comandos
composer require symfony/translation mkdir resource/translations/zh_CN/ -p echo "<?php return [ 'Too Many Requests' => 'Frecuencia de solicitudes limitada' ];" > resource/translations/zh_CN/messages.php php start.php restart
Interfaz
A veces los desarrolladores quieren llamar directamente al limitador de tasa en el código, consulte el siguiente código
<?php
namespace app\controller;
use RuntimeException;
use Webman\RateLimiter\Limiter;
class UserController {
public function sendSms(string $mobile): string
{
// Aquí mobile se usa como clave
Limiter::check($mobile, 5, 24*60*60, 'Cada número de teléfono puede recibir un máximo de 5 mensajes de texto al día');
return 'Mensaje de texto enviado con éxito';
}
}
Configuración
config/plugin/webman/rate-limiter/app.php
<?php
return [
'enable' => true,
'driver' => 'auto', // auto, apcu, memory, redis
'stores' => [
'redis' => [
'connection' => 'default',
]
],
// Las solicitudes de estas IP no tienen limitación de frecuencia (solamente cuando la clave es RateLimiter::IP es efectivo)
'ip_whitelist' => [
'127.0.0.1',
],
];
- enable: Si se habilita la limitación de tasa
- driver: Uno de los valores
auto
,apcu
,memory
,redis
, cuando se usaauto
, elegirá automáticamente uno entreapcu
ymemory
- stores: Configuración para
redis
,connection
corresponde a lakey
enconfig/redis.php
- ip_whitelist: Las IP de la lista blanca no serán limitadas (solo es efectivo cuando la clave es
RateLimiter::IP
)
Elección de controlador
memory
-
Introducción
No requiere la instalación de ninguna extensión, tiene mejor rendimiento. -
Restricciones de uso
La limitación sólo es efectiva para el proceso actual, no se comparten los datos de limitación entre múltiples procesos y tampoco soporta la limitación en clúster. -
Escenario adecuado
Entorno de desarrollo en Windows; negocios que no requieren una limitación estricta; resistencia a ataques CC.
apcu
-
Instalación de la extensión
Necesita instalar la extensión apcu y configurar en php.iniapc.enabled=1 apc.enable_cli=1
Si no sabe dónde se encuentra php.ini, puede buscar la ubicación de php.ini utilizando el comando
php --ini
. -
Introducción
Rendimiento ligeramente inferior a memory, admite la compartición de datos de limitación entre procesos. -
Restricciones de uso
No soporta clúster. -
Escenario adecuado
Cualquier entorno de desarrollo; escenarios de limitación en un solo servidor en producción; escenarios de clúster que no requieren limitación estricta; resistencia a ataques CC.
redis
-
Dependencias
Necesita instalar la extensión redis y el componente Redis, con el siguiente comando de instalacióncomposer require -W illuminate/redis illuminate/events
-
Introducción
Rendimiento inferior al de apcu, admite limitación precisa tanto en un solo servidor como en clúster. -
Escenario adecuado
Entorno de desarrollo; entorno en un solo servidor en producción; entorno de clúster.