ตัวจำกัดอัตรา
ตัวจำกัดอัตรา webman รองรับการจำกัดด้วย annotation
รองรับไดรเวอร์ apcu, redis และ memory
ที่อยู่ซอร์สโค้ด
https://github.com/webman-php/limiter
การติดตั้ง
composer require webman/limiter
การใช้งาน
<?php
namespace app\controller;
use RuntimeException;
use support\limiter\annotation\Limit;
class UserController
{
#[Limit(limit: 10)]
public function index(): string
{
// ค่าเริ่มต้นคือจำกัดตาม IP ช่วงเวลาเริ่มต้น 1 วินาที
return 'สูงสุด 10 คำขอต่อ IP ต่อวินาที';
}
#[Limit(limit: 100, ttl: 60, key: Limit::UID)]
public function search(): string
{
// key: Limit::UID จำกัดตาม ID ผู้ใช้ ต้องมี session('user.id') ไม่ว่าง
return 'สูงสุด 100 การค้นหาต่อผู้ใช้ต่อ 60 วินาที';
}
#[Limit(limit: 1, ttl: 60, key: Limit::SID, message: '1 อีเมลต่อคนต่อนาทีเท่านั้น')]
public function sendMail(): string
{
// key: Limit::SID จำกัดตาม session_id
return 'ส่งอีเมลสำเร็จ';
}
#[Limit(limit: 100, ttl: 24*60*60, key: 'coupon', message: 'คูปองวันนี้หมดแล้ว กรุณาลองใหม่พรุ่งนี้')]
#[Limit(limit: 1, ttl: 24*60*60, key: Limit::UID, message: 'ผู้ใช้แต่ละคนรับคูปองได้วันละ 1 ครั้งเท่านั้น')]
public function coupon(): string
{
// key: 'coupon' คีย์กำหนดเองสำหรับจำกัดทั่วโลก สูงสุด 100 คูปองต่อวัน
// จำกัดตาม ID ผู้ใช้ด้วย ผู้ใช้แต่ละคนรับคูปองได้วันละ 1 ครั้ง
return 'ส่งคูปองสำเร็จ';
}
#[Limit(limit: 5, ttl: 24*60*60, key: [UserController::class, 'getMobile'], message: 'สูงสุด 5 SMS ต่อหมายเลขต่อวัน')]
public function sendSms2(): string
{
// เมื่อ key เป็นตัวแปร ใช้ [คลาส, เมธอด_static] เช่น [UserController::class, 'getMobile'] ใช้ค่าที่คืนจาก UserController::getMobile() เป็นคีย์
return 'ส่ง SMS สำเร็จ';
}
/**
* คีย์กำหนดเอง ดึงหมายเลขโทรศัพท์ ต้องเป็นเมธอด static
* @return string
*/
public static function getMobile(): string
{
return request()->get('mobile');
}
#[Limit(limit: 1, ttl: 10, key: Limit::IP, message: 'จำกัดอัตรา', exception: RuntimeException::class)]
public function testException(): string
{
// ข้อยกเว้นเริ่มต้นเมื่อเกิน: support\limiter\RateLimitException เปลี่ยนได้ผ่านพารามิเตอร์ exception
return 'ok';
}
}
หมายเหตุ
- ใช้อัลกอริทึมหน้าต่างคงที่
- ช่วงเวลา ttl เริ่มต้น: 1 วินาที
- ตั้งค่าหน้าต่างผ่าน ttl เช่น
ttl:60สำหรับ 60 วินาที - มิติจำกัดเริ่มต้น: IP (เริ่มต้น
127.0.0.1ไม่จำกัด ดูการกำหนดค่าด้านล่าง) - ในตัว: จำกัด IP, UID (ต้องมี
session('user.id')ไม่ว่าง), SID (ตามsession_id) - เมื่อใช้ nginx proxy ส่ง header
X-Forwarded-Forสำหรับจำกัด IP ดู nginx proxy - เรียก
support\limiter\RateLimitExceptionเมื่อเกิน กำหนดคลาสข้อยกเว้นผ่านexception:xx - ข้อความข้อผิดพลาดเริ่มต้นเมื่อเกิน:
Too Many Requestsกำหนดข้อความผ่านmessage:xx - ข้อความข้อผิดพลาดเริ่มต้นแก้ไขได้ผ่าน การแปล อ้างอิง Linux:
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
API
บางครั้งนักพัฒนาต้องการเรียกตัวจำกัดอัตราโดยตรงในโค้ด ดูตัวอย่างต่อไปนี้:
<?php
namespace app\controller;
use RuntimeException;
use support\limiter\Limiter;
class UserController {
public function sendSms(string $mobile): string
{
// ใช้ mobile เป็นคีย์ที่นี่
Limiter::check($mobile, 5, 24*60*60, 'สูงสุด 5 SMS ต่อหมายเลขต่อวัน');
return 'ส่ง SMS สำเร็จ';
}
}
การกำหนดค่า
config/plugin/webman/limiter/app.php
<?php
use support\limiter\RateLimitException;
return [
'enable' => true,
'driver' => 'auto', // auto, apcu, memory, redis
'stores' => [
'redis' => [
'connection' => 'default',
]
],
// IP เหล่านี้ไม่ถูกจำกัด (มีผลเฉพาะเมื่อ key เป็น Limit::IP)
'ip_whitelist' => [
'127.0.0.1',
],
'exception' => RateLimitException::class
];
- enable: เปิดใช้งานการจำกัดอัตรา
- driver: หนึ่งใน
auto,apcu,memory,redis;autoเลือกอัตโนมัติระหว่างapcu(ลำดับความสำคัญ) และmemory - stores: การกำหนดค่า Redis
connectionตรงกับคีย์ในconfig/redis.php - ip_whitelist: IP ใน whitelist ไม่ถูกจำกัด (มีผลเฉพาะเมื่อ key เป็น
Limit::IP)
การเลือก driver
memory
-
คำอธิบาย
ไม่ต้องติดตั้งส่วนขยาย ประสิทธิภาพดีที่สุด -
ข้อจำกัด
จำกัดเฉพาะกระบวนการปัจจุบัน ไม่แชร์ข้อมูลระหว่างกระบวนการ ไม่รองรับการจำกัดคลัสเตอร์ -
สถานการณ์การใช้งาน
สภาพแวดล้อมพัฒนา Windows; ธุรกิจที่ไม่ต้องจำกัดเข้มงวด; ป้องกันการโจมตี CC
apcu
- การติดตั้งส่วนขยาย
ต้องติดตั้งส่วนขยาย apcu และตั้งค่า php.ini:
apc.enabled=1
apc.enable_cli=1
หาตำแหน่ง php.ini ด้วยคำสั่ง php --ini
-
คำอธิบาย
ประสิทธิภาพดีมาก รองรับการแชร์ข้อมูลหลายกระบวนการ -
ข้อจำกัด
ไม่รองรับคลัสเตอร์ -
สถานการณ์การใช้งาน
สภาพแวดล้อมพัฒนาใดๆ; จำกัดเซิร์ฟเวอร์เดี่ยวในโปรดักชัน; คลัสเตอร์ที่ไม่ต้องจำกัดเข้มงวด; ป้องกันการโจมตี CC
redis
- การพึ่งพา
ต้องติดตั้งส่วนขยาย redis และคอมโพเนนต์ Redis คำสั่งติดตั้ง:
composer require -W webman/redis illuminate/events
-
คำอธิบาย
ประสิทธิภาพต่ำกว่า apcu รองรับการจำกัดแม่นยำเซิร์ฟเวอร์เดี่ยวและคลัสเตอร์ -
สถานการณ์การใช้งาน
สภาพแวดล้อมพัฒนา; เซิร์ฟเวอร์เดี่ยวในโปรดักชัน; สภาพแวดล้อมคลัสเตอร์