Limitador de Taxa
O limitador de taxa do webman suporta limitação de taxa por anotações.
Suporta drivers apcu, redis e memory.
Endereço do Código Fonte
https://github.com/webman-php/rate-limiter
Instalação
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
{
// O limite padrão é por IP, com um intervalo de 1 segundo
return 'Até 10 requisições por segundo para cada IP';
}
#[RateLimiter(limit: 100, ttl: 60, key: RateLimiter::UID)]
public function search(): string
{
// key: RateLimiter::UID, limita a taxa com base no ID do usuário, exige que session('user.id') não seja nulo
return 'Até 100 buscas a cada 60 segundos por usuário';
}
#[RateLimiter(limit: 1, ttl: 60, key: RateLimiter::SID, message: 'Cada pessoa pode enviar apenas 1 e-mail por minuto')]
public function sendMail(): string
{
// key: RateLimiter::SID, limita a taxa com base no session_id
return 'E-mail enviado com sucesso';
}
#[RateLimiter(limit: 100, ttl: 24*60*60, key: 'coupon', message: 'Os cupons de hoje já foram distribuídos, volte amanhã')]
#[RateLimiter(limit: 1, ttl: 24*60*60, key: RateLimiter::UID, message: 'Cada usuário pode retirar apenas 1 cupom por dia')]
public function coupon(): string
{
// key: 'coupon', aqui 'coupon' é uma chave personalizada, limitando globalmente a taxa com a chave coupon, com um máximo de 100 cupons por dia
// Também limita a taxa com base no ID do usuário, cada usuário pode retirar apenas 1 cupom por dia
return 'Cupom enviado com sucesso';
}
#[RateLimiter(limit: 5, ttl: 24*60*60, key: [UserController::class, 'getMobile'], message: 'Cada número de telefone pode receber até 5 mensagens por dia')]
public function sendSms2(): string
{
// Quando a chave é uma variável, pode-se usar a forma [classe, método estático] para obter a chave, por exemplo, [UserController::class, 'getMobile'] chamará o método getMobile() da classe UserController que retornará a chave
return 'Mensagem enviada com sucesso';
}
/**
* Chave personalizada, obtendo o número de telefone, deve ser um método estático
* @return string
*/
public static function getMobile(): string
{
return request()->get('mobile');
}
#[RateLimiter(limit: 1, ttl: 10, key: RateLimiter::IP, message: 'Frequência limitada', exception: RuntimeException::class)]
public function testException(): string
{
// A exceção padrão quando o limite é ultrapassado é Webman\RateLimiter\RateLimitException, que pode ser alterada através do parâmetro exception
return 'ok';
}
}
Observações
- O intervalo de tempo padrão é de 1 segundo
- Pode-se definir o intervalo de tempo usando ttl, por exemplo,
ttl:60
significa 60 segundos - O limite padrão é por IP (o IP
127.0.0.1
não tem limitação, consulte a seção de configuração abaixo) - Inclui limitação por IP, UID (exige que
session('user.id')
não seja nulo), e SID (com base emsession_id
) - Se você estiver usando um proxy nginx, ao limitar por IP, o cabeçalho
X-Forwarded-For
deve ser passado, consulte proxy nginx - Quando o limite é ultrapassado, a exceção
Webman\RateLimiter\RateLimitException
será acionada, pode-se personalizar a classe de exceção comexception:xx
- Quando a exceção é acionada, a mensagem de erro padrão é
Too Many Requests
, pode-se personalizar a mensagem de erro commessage:xx
- A mensagem de erro padrão também pode ser alterada através de traduções, para Linux, consulte os seguintes comandos
composer require symfony/translation mkdir resource/translations/zh_CN/ -p echo "<?php return [ 'Too Many Requests' => 'Frequência de requisições limitada' ];" > resource/translations/zh_CN/messages.php php start.php restart
Interface
Às vezes, os desenvolvedores desejam chamar o limitador diretamente no código, consulte o código abaixo
<?php
namespace app\controller;
use RuntimeException;
use Webman\RateLimiter\Limiter;
class UserController {
public function sendSms(string $mobile): string
{
// Aqui mobile é a chave
Limiter::check($mobile, 5, 24*60*60, 'Cada número de telefone pode receber até 5 mensagens por dia');
return 'Mensagem enviada com sucesso';
}
}
Configuração
config/plugin/webman/rate-limiter/app.php
<?php
return [
'enable' => true,
'driver' => 'auto', // auto, apcu, memory, redis
'stores' => [
'redis' => [
'connection' => 'default',
]
],
// As requisições desses IPs não têm limitação de frequência (somente é válido quando a chave é RateLimiter::IP)
'ip_whitelist' => [
'127.0.0.1',
],
];
- enable: Habilitar limite de taxa
- driver: Um dos valores
auto
,apcu
,memory
,redis
, ao usarauto
irá escolher automaticamente entreapcu
ememory
- stores: Configuração do
redis
,connection
corresponde àkey
emconfig/redis.php
- ip_whitelist: IPs na lista branca não serão limitados (somente é válido para a chave
RateLimiter::IP
)
Escolha do driver
memory
-
Introdução
Não requer a instalação de nenhuma extensão, melhor desempenho. -
Limitações de Uso
A limitação de taxa é válida apenas para o processo atual, os dados de limitação de taxa não são compartilhados entre múltiplos processos e não suportam limitação em cluster. -
Cenários Adequados
Ambiente de desenvolvimento Windows; negócios que não exigem uma limitação rigorosa; defesa contra ataques de CC.
apcu
-
Instalação da Extensão
É necessário instalar a extensão apcu e configurar no php.iniapc.enabled=1 apc.enable_cli=1
Se você não souber a localização do php.ini, pode encontrar usando o comando
php --ini
-
Introdução
Desempenho ligeiramente inferior ao memory, suporta compartilhamento de dados de limitação de taxa entre múltiplos processos. -
Limitações de Uso
Não suporta cluster -
Cenários Adequados
Qualquer ambiente de desenvolvimento; cenários de limitação de taxa em máquinas simples online; cenários em cluster que não exigem limitação rigorosa; defesa contra ataques de CC.
redis
-
Dependências
É necessário instalar a extensão redis e o componente Redis, comando de instalaçãocomposer require -W illuminate/redis illuminate/events
-
Introdução
Desempenho inferior ao apcu, suporta limitação de taxa precisa tanto em máquinas simples quanto em cluster. -
Cenários Adequados
Ambiente de desenvolvimento; ambiente online em máquina única; ambiente em cluster