Rate Limiter
Der Webman Rate Limiter unterstützt Annotation-Rate-Limiting.
Er unterstützt die Treiber apcu, redis und memory.
Quellcode-Adresse
https://github.com/webman-php/rate-limiter
Installation
composer require webman/rate-limiter
Nutzung
<?php
namespace app\controller;
use RuntimeException;
use Webman\RateLimiter\Annotation\RateLimiter;
class UserController
{
#[RateLimiter(limit: 10)]
public function index(): string
{
// Standardmäßig Limiting nach IP, die Standard-Zeitspanne beträgt 1 Sekunde
return 'Maximal 10 Anfragen pro Sekunde und IP';
}
#[RateLimiter(limit: 100, ttl: 60, key: RateLimiter::UID)]
public function search(): string
{
// key: RateLimiter::UID, Limiting basierend auf der Benutzer-ID, `session('user.id')` darf nicht leer sein
return 'Maximal 100 Suchen alle 60 Sekunden pro Benutzer';
}
#[RateLimiter(limit: 1, ttl: 60, key: RateLimiter::SID, message: 'Jeder kann nur einmal pro Minute eine E-Mail senden')]
public function sendMail(): string
{
// key: RateLimiter::SID, Limiting basierend auf der session_id
return 'E-Mail erfolgreich gesendet';
}
#[RateLimiter(limit: 100, ttl: 24*60*60, key: 'coupon', message: 'Die Coupons für heute sind bereits vergeben, bitte kommen Sie morgen wieder')]
#[RateLimiter(limit: 1, ttl: 24*60*60, key: RateLimiter::UID, message: 'Jeder Benutzer kann nur einmal täglich einen Coupon erhalten')]
public function coupon(): string
{
// key: 'coupon', hier ist der Coupon ein benutzerdefinierter Schlüssel, der global Limiting mit dem Schlüssel coupon durchführt, maximal 100 Coupons pro Tag
// Gleichzeitig wird nach Benutzer-ID limitiert, jeder Benutzer kann täglich nur einen Coupon erhalten
return 'Coupon erfolgreich versendet';
}
#[RateLimiter(limit: 5, ttl: 24*60*60, key: [UserController::class, 'getMobile'], message: 'Maximal 5 SMS pro Tag pro Telefonnummer')]
public function sendSms2(): string
{
// Wenn der Schlüssel eine Variable ist, kann er im Format [Klasse, Statische Methode] abgerufen werden, z.B. [UserController::class, 'getMobile'] ruft den Rückgabewert der Methode getMobile() der UserController-Klasse ab
return 'SMS erfolgreich gesendet';
}
/**
* Benutzerdefinierter Schlüssel, um die Telefonnummer zu erhalten, muss eine statische Methode sein
* @return string
*/
public static function getMobile(): string
{
return request()->get('mobile');
}
#[RateLimiter(limit: 1, ttl: 10, key: RateLimiter::IP, message: 'Frequenz eingeschränkt', exception: RuntimeException::class)]
public function testException(): string
{
// Bei Überschreitung wird standardmäßig die Ausnahme Webman\RateLimiter\RateLimitException ausgelöst, die über den Parameter exception geändert werden kann
return 'ok';
}
}
Hinweise
- Der Standard-Zeitintervall beträgt 1 Sekunde.
- Der Zeitintervall kann mit ttl eingestellt werden, z.B.
ttl:60
für 60 Sekunden. - Die Standard-Limiting-Dimension ist IP-Limiting (standardmäßig bleibt
127.0.0.1
unbegrenzt, siehe Abschnitt zur Konfiguration weiter unten). - Eingebaute IP-Limiting, UID-Limiting (erfordert, dass
session('user.id')
nicht leer ist), SID-Limiting (mithilfe dersession_id
). - Wenn Nginx als Proxy verwendet wird, muss der Header
X-Forwarded-For
für IP-Limiting übergeben werden, siehe nginx proxy. - Bei Überschreitung wird die Ausnahme
Webman\RateLimiter\RateLimitException
ausgelöst, die überexception:xx
eine benutzerdefinierte Ausnahme-Klasse zulässt. - Bei Auslösung einer Ausnahme bei Überschreitung ist die Standard-Fehlermeldung
Too Many Requests
, die übermessage:xx
angepasst werden kann. - Die Standard-Fehlermeldung kann auch über Übersetzungen geändert werden, verwenden Sie dazu die folgenden Linux-Befehle:
composer require symfony/translation mkdir resource/translations/zh_CN/ -p echo "<?php return [ 'Too Many Requests' => '请求频率受限' ];" > resource/translations/zh_CN/messages.php php start.php restart
Schnittstelle
Manchmal möchten Entwickler den Rate Limiter direkt im Code aufrufen, siehe den folgenden Code
<?php
namespace app\controller;
use RuntimeException;
use Webman\RateLimiter\Limiter;
class UserController {
public function sendSms(string $mobile): string
{
// Hier ist mobile der Schlüssel
Limiter::check($mobile, 5, 24*60*60, 'Maximal 5 SMS pro Tag pro Telefonnummer');
return 'SMS erfolgreich gesendet';
}
}
Konfiguration
config/plugin/webman/rate-limiter/app.php
<?php
return [
'enable' => true,
'driver' => 'auto', // auto, apcu, memory, redis
'stores' => [
'redis' => [
'connection' => 'default',
]
],
// Diese IPs werden nicht auf Frequenz begrenzt (nur wenn der Schlüssel RateLimiter::IP ist)
'ip_whitelist' => [
'127.0.0.1',
],
];
- enable: Ob das Rate Limiting aktiviert ist.
- driver: Einen der Werte
auto
apcu
memory
redis
. Bei der Verwendung vonauto
wird automatisch ein Wert zwischenapcu
undmemory
ausgewählt. - stores: Konfiguration für
redis
,connection
entspricht dem entsprechenden Schlüssel inconfig/redis.php
. - ip_whitelist: IPs in der Whitelist werden nicht limitiert (nur wirksam, wenn der Schlüssel
RateLimiter::IP
ist).
Auswahl des Treibers
memory
-
Einführung
memory
erfordert keine zusätzliche Installation und bietet die beste Leistung. -
Nutzungseinschränkungen
Limiting gilt nur für den aktuellen Prozess, die Limiting-Daten werden nicht zwischen mehreren Prozessen geteilt und unterstützen auch kein Cluster-Limiting. -
Anwendungsfälle
Windows-Entwicklungsumgebung; Geschäftslogik, die kein strenges Limiting benötigt; Abwehr von CC-Angriffen.
apcu
-
Erweiterungsinstallation
Es muss die apcu-Erweiterung installiert und in der php.ini eingestellt werden:apc.enabled=1 apc.enable_cli=1
Falls der Standort der php.ini unbekannt ist, kann dieser mit dem Befehl
php --ini
festgestellt werden. -
Einführung
Die Leistung ist etwas niedriger alsmemory
, unterstützt die gemeinsame Nutzung von Limiting-Daten über mehrere Prozesse. -
Nutzungseinschränkungen
Unterstützt kein Cluster. -
Anwendungsfälle
Beliebige Entwicklungsumgebung; Szenarien mit Einzelmaschinen-Limiting in der Produktionsumgebung; Clusterumgebungen, die kein strenges Limiting erfordern; Abwehr von CC-Angriffen.
redis
-
Abhängigkeit
Es muss die redis-Erweiterung installiert und die Redis-Komponente installiert werden, Installationsbefehl:composer require -W illuminate/redis illuminate/events
-
Einführung
Die Leistung ist niedriger als beiapcu
, unterstützt sowohl Einzelmaschinen als auch Cluster-Limiting präzise. -
Anwendungsfälle
Entwicklungsumgebungen; Einzelmaschine in der Produktionsumgebung; Cluster-Umgebungen.