Limiteur de Taux
Le limiteur de taux de webman prend en charge la limitation par annotations.
Il prend en charge les pilotes apcu, redis et memory.
Adresse du Code Source
https://github.com/webman-php/rate-limiter
Installation
composer require webman/rate-limiter
Utilisation
<?php
namespace app\controller;
use RuntimeException;
use Webman\RateLimiter\Annotation\RateLimiter;
class UserController
{
#[RateLimiter(limit: 10)]
public function index(): string
{
// Par défaut, la limitation est basée sur l'IP, la durée par défaut est de 1 seconde
return '10 requêtes maximum par seconde pour chaque IP';
}
#[RateLimiter(limit: 100, ttl: 60, key: RateLimiter::UID)]
public function search(): string
{
// key: RateLimiter::UID, limitation par ID utilisateur, session('user.id') ne doit pas être vide
return '100 recherches maximum par utilisateur toutes les 60 secondes';
}
#[RateLimiter(limit: 1, ttl: 60, key: RateLimiter::SID, message: 'Chaque personne peut envoyer un e-mail une fois par minute')]
public function sendMail(): string
{
// key: RateLimiter::SID, limitation basée sur session_id
return 'E-mail envoyé avec succès';
}
#[RateLimiter(limit: 100, ttl: 24*60*60, key: 'coupon', message: 'Les coupons d\'aujourd\'hui ont tous été envoyés, revenez demain')]
#[RateLimiter(limit: 1, ttl: 24*60*60, key: RateLimiter::UID, message: 'Chaque utilisateur ne peut réclamer qu\'un coupon par jour')]
public function coupon(): string
{
// key: 'coupon', ici coupon est une clé personnalisée, limitant le nombre de coupons à 100 par jour
// Dans le même temps, limitation par ID utilisateur, chaque utilisateur ne peut réclamer qu'un coupon par jour
return 'Coupon envoyé avec succès';
}
#[RateLimiter(limit: 5, ttl: 24*60*60, key: [UserController::class, 'getMobile'], message: 'Chaque numéro de portable peut recevoir au maximum 5 SMS par jour')]
public function sendSms2(): string
{
// Lorsque la clé est une variable, on peut utiliser [classe, méthode statique] pour obtenir la clé, par exemple [UserController::class, 'getMobile'] renvoie la valeur de la méthode getMobile() de UserController
return 'SMS envoyé avec succès';
}
/**
* Clé personnalisée, obtient le numéro de portable, doit être une méthode statique
* @return string
*/
public static function getMobile(): string
{
return request()->get('mobile');
}
#[RateLimiter(limit: 1, ttl: 10, key: RateLimiter::IP, message: 'Limite de fréquence atteinte', exception: RuntimeException::class)]
public function testException(): string
{
// Exception par défaut lors du dépassement est Webman\RateLimiter\RateLimitException, peut être changée par le paramètre exception
return 'ok';
}
}
Remarques
- La durée par défaut est de 1 seconde
- Vous pouvez définir une durée via ttl, par exemple
ttl:60
pour 60 secondes - La dimension de limitation par défaut est basée sur l'IP (par défaut
127.0.0.1
n'a pas de limitation, voir la configuration ci-dessous) - Prise en charge des limitations basées sur l'IP, UID (requiert que
session('user.id')
ne soit pas vide), SID (basé sursession_id
) - Si vous utilisez un proxy nginx, pour la limitation IP, vous devez transmettre l'en-tête
X-Forwarded-For
, voir proxy nginx - Lorsqu'une limitation est atteinte, cela déclenche l'exception
Webman\RateLimiter\RateLimitException
, vous pouvez personnaliser la classe d'exception avecexception:xx
- Lorsqu'une limite est atteinte, le message d'erreur par défaut est
Too Many Requests
, il peut être personnalisé avecmessage:xx
- Le message d'erreur par défaut peut également être modifié via traduction, sous Linux, consultez les commandes suivantes
composer require symfony/translation mkdir resource/translations/zh_CN/ -p echo "<?php return [ 'Too Many Requests' => 'Fréquence de demande limitée' ];" > resource/translations/zh_CN/messages.php php start.php restart
Interface
Parfois, les développeurs souhaitent appeler directement le limiteur dans le code, voir l'exemple ci-dessous
<?php
namespace app\controller;
use RuntimeException;
use Webman\RateLimiter\Limiter;
class UserController {
public function sendSms(string $mobile): string
{
// ici mobile est utilisé comme clé
Limiter::check($mobile, 5, 24*60*60, 'Chaque numéro de portable peut recevoir au maximum 5 SMS par jour');
return 'SMS envoyé avec succès';
}
}
Configuration
config/plugin/webman/rate-limiter/app.php
<?php
return [
'enable' => true,
'driver' => 'auto', // auto, apcu, memory, redis
'stores' => [
'redis' => [
'connection' => 'default',
]
],
// Ces IP ne subissent pas de limitation de fréquence (valide uniquement quand la clé est RateLimiter::IP)
'ip_whitelist' => [
'127.0.0.1',
],
];
- enable: Activer la limitation
- driver: Une valeur parmi
auto
apcu
memory
redis
, en utilisantauto
, il choisira automatiquement entreapcu
etmemory
- stores: Configuration
redis
,connection
correspond à lakey
dansconfig/redis.php
- ip_whitelist: Les IP de la liste blanche ne seront pas soumises à la limitation (valide uniquement lorsque la clé est
RateLimiter::IP
)
Choix du pilote
memory
-
Introduction
Aucun module à installer, meilleures performances. -
Limitations d'utilisation
La limitation ne s'applique qu'au processus actuel, les données de limitation ne sont pas partagées entre plusieurs processus, et ne prend pas en charge la limitation en cluster. -
Scénarios d'application
Environnement de développement Windows ; affaires sans limitation stricte ; défense contre les attaques CC.
apcu
-
Installation de l'extension
L'extension apcu doit être installée, et dans php.ini doit être régléapc.enabled=1 apc.enable_cli=1
Si vous ne savez pas où se trouve le fichier php.ini, vous pouvez le trouver en exécutant la commande
php --ini
-
Introduction
Performance légèrement inférieure à celle de memory, prend en charge le partage des données de limitation entre plusieurs processus. -
Limitations d'utilisation
Ne prend pas en charge les clusters -
Scénarios d'application
Tout environnement de développement ; scénarios de limitation sur une machine unique en ligne ; scénarios de clusters sans limitation stricte ; défense contre les attaques CC.
redis
-
Dépendances
L'extension redis doit être installée, et le composant Redis doit être installé, commande d'installationcomposer require -W illuminate/redis illuminate/events
-
Introduction
Performance inférieure à apcu, prend en charge la limitation précise pour une seule machine et aussi pour des clusters -
Scénarios d'application
Environnement de développement ; environnement de machine unique en ligne ; environnement de cluster