Hız Sınırlandırıcısı

Webman hız sınırlayıcı, anotasyon ile hız sınırlamayı destekler.
apcu, redis, memory sürücülerini destekler.

Kaynak Kodu Adresi

https://github.com/webman-php/rate-limiter

Kurulum

composer require webman/rate-limiter

Kullanım

<?php
namespace app\controller;

use RuntimeException;
use Webman\RateLimiter\Annotation\RateLimiter;

class UserController
{

    #[RateLimiter(limit: 10)]
    public function index(): string
    {
        // Varsayılan olarak IP hızı sınırlaması, varsayılan birim zaman 1 saniyedir
        return 'Her bir ip için saniyede en fazla 10 isteğe izin verilir';
    }

    #[RateLimiter(limit: 100, ttl: 60, key: RateLimiter::UID)]
    public function search(): string
    {
        // key: RateLimiter::UID, kullanıcı ID'sine göre hız sınırlaması, session('user.id') boş olmamalıdır
        return 'Her bir kullanıcı için 60 saniyede en fazla 100 arama';
    }

    #[RateLimiter(limit: 1, ttl: 60, key: RateLimiter::SID, message: 'Her kişi dakikada yalnızca 1 e-posta gönderebilir')]
    public function sendMail(): string
    {
        // key: RateLimiter::SID, session_id'e göre hız sınırlaması
        return 'E-posta gönderimi başarılı';
    }

    #[RateLimiter(limit: 100, ttl: 24*60*60, key: 'coupon', message: 'Bugünün kuponları tükenmiştir, lütfen yarın tekrar gelin')]
    #[RateLimiter(limit: 1, ttl: 24*60*60, key: RateLimiter::UID, message: 'Her bir kullanıcı için günde yalnızca bir kez kupon alınabilir')]
    public function coupon(): string
    {
        // key: 'coupon', burada coupon özel bir anahtardır, yani global olarak coupon anahtarı ile hız sınırlandırması yapılır ve günde en fazla 100 kupon dağıtılır
        // Aynı zamanda kullanıcı ID'sine göre hız sınırlaması yapılır, her bir kullanıcı günde yalnızca bir kupon alabilir.
        return 'Kupon gönderimi başarılı';
    }

    #[RateLimiter(limit: 5, ttl: 24*60*60, key: [UserController::class, 'getMobile'], message: 'Her telefon numarası için günde en fazla 5 SMS')]
    public function sendSms2(): string
    {
        // Anahtar bir değişken olduğunda [sınıf, statik yöntem] şeklinde anahtarı almak için kullanılabilir, örneğin [UserController::class, 'getMobile'] UserController'ın getMobile() yönteminin dönüş değerini anahtar olarak alır.
        return 'SMS gönderimi başarılı';
    }

    /**
     * Özel anahtar, telefon numarasını alır, statik bir yöntem olmalıdır
     * @return string
     */
    public static function getMobile(): string
    {
        return request()->get('mobile');
    }

    #[RateLimiter(limit: 1, ttl: 10, key: RateLimiter::IP, message: 'Frekans sınırlı', exception: RuntimeException::class)]
    public function testException(): string
    {
        // Limit aşıldığında varsayılan istisna Webman\RateLimiter\RateLimitException'dır, exception parametresi ile değiştirilebilir
        return 'tamam';
    }

}

Açıklama

  • Varsayılan birim zaman aralığı 1 saniyedir.
  • Örneğin ttl:60, birim zaman aralığını 60 saniye olarak ayarlamak için kullanılabilir.
  • Varsayılan hız sınırlama boyutu IP hız sınırlamasıdır (varsayılan 127.0.0.1 hız sınırlaması yoktur, aşağıdaki konfigürasyon bölümüne bakınız).
  • Yerleşik IP hız sınırlaması, UID hız sınırlaması (session('user.id') boş olmamalıdır), SID hız sınırlaması (session_id'ye göre hız sınırlaması).
  • Nginx proxy kullanılıyorsa, IP hız sınırlamasında X-Forwarded-For başlığının iletilmesi gereklidir, nginx proxy bölümüne bakınız.
  • Limit aşıldığında Webman\RateLimiter\RateLimitException istisnası tetiklenir, exception:xx ile özel istisna sınıfı tanımlanabilir.
  • Limit aşımı sırasında hata mesajı varsayılan olarak Too Many Requests'tır, message:xx ile hata mesajı özelleştirilebilir.
  • Varsayılan hata mesajı da çok dilli olarak değiştirilebilir, Linux için aşağıdaki komutları referans alın.
    composer require symfony/translation
    mkdir resource/translations/zh_CN/ -p
    echo "<?php
    return [
    'Too Many Requests' => 'İstek frekansı sınırlı'
    ];" > resource/translations/zh_CN/messages.php
    php start.php restart

Arayüz

Bazen geliştiriciler hız sınırlayıcıyı doğrudan kodda çağırmak isteyebilir, aşağıdaki kodu referans alabilirsiniz.

<?php
namespace app\controller;

use RuntimeException;
use Webman\RateLimiter\Limiter;

class UserController {

    public function sendSms(string $mobile): string
    {
        // Burada mobile anahtar olarak kullanılır
        Limiter::check($mobile, 5, 24*60*60, 'Her telefon numarası için günde en fazla 5 SMS');
        return 'SMS gönderimi başarılı';
    }
}

Konfigürasyon

config/plugin/webman/rate-limiter/app.php

<?php
return [
    'enable' => true,
    'driver' => 'auto', // auto, apcu, memory, redis
    'stores' => [
        'redis' => [
            'connection' => 'default',
        ]
    ],
    // Bu ip'lerin istekleri hız kısıtlamasına tabi tutulmaz (sadece key RateLimiter::IP olduğunda etkilidir)
    'ip_whitelist' => [
        '127.0.0.1',
    ],
];
  • enable: Hız sınırlayıcısını açma
  • driver: auto, apcu, memory, veya redis'den bir değer, auto kullanıldığında apcu ve memory'den biri otomatik olarak seçilir.
  • stores: redis ayarı, connection config/redis.php'deki ilgili key'yi temsil eder.
  • ip_whitelist: Beyaz listedeki ip'ler hız sınırlamasına tabi tutulmaz (sadece key RateLimiter::IP olduğunda etkilidir).

Sürücü Seçimi

memory

  • Tanıtım
    Herhangi bir uzantı yüklemeye gerek yoktur, en iyi performansa sahiptir.

  • Kullanım Sınırlamaları
    Hız sınırlaması yalnızca mevcut süreçte etkilidir, birden fazla süreç arasında hız sınırlama verileri paylaşılmaz ve aynı zamanda küme hızı sınırlamasını desteklemez.

  • Uygulama Senaryoları
    Windows geliştirme ortamı; Sıkı hız sınırlaması gerektirmeyen işler; CC saldırılarına karşı koruma.

apcu

  • Uzantıyı Yükleme
    apcu uzantısının yüklenmesi gerekir ve php.ini dosyasında şu ayar yapılmalıdır:

    apc.enabled=1
    apc.enable_cli=1

    php.ini dosyasının konumunu bilmiyorsanız, php --ini komutu ile bulabilirsiniz.

  • Tanıtım
    performansı memory'den biraz daha düşüktür, çoklu süreçler arasında hız sınırlama verilerini paylaşmayı destekler.

  • Kullanım Sınırlamaları
    Küme desteği yoktur.

  • Uygulama Senaryoları
    Herhangi bir geliştirme ortamı; Çevrimiçi tek makina hız sınırlama senaryoları; Küme içinde sıkı hız sınırlaması gerektirmeyen senaryolar; CC saldırılarına karşı koruma.

redis

  • Bağımlılıklar
    redis uzantısının yüklenmesi gerekir ve Redis bileşeni yüklenmelidir, yükleme komutu:

    composer require -W illuminate/redis illuminate/events
  • Tanıtım
    performansı apcu'dan daha düşüktür, hem tek makina hem de küme için hassas hız sınırlamayı destekler.

  • Uygulama Senaryoları
    Geliştirme ortamı; Çevrimiçi tek makina ortamı; Küme ortamı.