제한기
webman 제한기는 주석 기반의 제한을 지원합니다.
apcu, redis, memory 드라이버를 지원합니다.
소스코드 주소
https://github.com/webman-php/rate-limiter
설치
composer require webman/rate-limiter
사용법
<?php
namespace app\controller;
use RuntimeException;
use Webman\RateLimiter\Annotation\RateLimiter;
class UserController
{
#[RateLimiter(limit: 10)]
public function index(): string
{
// 기본적으로 IP 기반 제한, 기본 시간 단위는 1초입니다.
return '각 IP는 1초에 최대 10개의 요청을 보낼 수 있습니다.';
}
#[RateLimiter(limit: 100, ttl: 60, key: RateLimiter::UID)]
public function search(): string
{
// key: RateLimiter::UID, 사용자 ID를 기준으로 제한, session('user.id')가 비어있지 않아야 합니다.
return '각 사용자에 대해 60초에 최대 100번의 검색이 가능합니다.';
}
#[RateLimiter(limit: 1, ttl: 60, key: RateLimiter::SID, message: '각 사람은 1분에 1개의 이메일만 보낼 수 있습니다.')]
public function sendMail(): string
{
// key: RateLimiter::SID, session_id를 기준으로 제한합니다.
return '이메일 발송 성공';
}
#[RateLimiter(limit: 100, ttl: 24*60*60, key: 'coupon', message: '오늘의 쿠폰은 모두 소진되었습니다. 내일 다시 오세요.')]
#[RateLimiter(limit: 1, ttl: 24*60*60, key: RateLimiter::UID, message: '각 사용자는 하루에 한 번만 쿠폰을 받을 수 있습니다.')]
public function coupon(): string
{
// key: 'coupon', 여기서 coupon은 사용자 정의 key로, 전역적으로 coupon을 기준으로 제한하며, 하루에 최대 100개의 쿠폰을 발급합니다.
// 동시에 사용자 ID를 기준으로 제한하여, 각 사용자는 하루에 한 번만 쿠폰을 받을 수 있습니다.
return '쿠폰 발송 성공';
}
#[RateLimiter(limit: 5, ttl: 24*60*60, key: [UserController::class, 'getMobile'], message: '각 전화번호는 하루에 최대 5개의 SMS를 받을 수 있습니다.')]
public function sendSms2(): string
{
// key가 변수를 사용할 때, [클래스, 정적 메소드]의 방식으로 key를 가져올 수 있습니다. 예를 들어 [UserController::class, 'getMobile']는 UserController의 getMobile() 메소드를 호출하여 반환되는 값을 key로 사용합니다.
return 'SMS 발송 성공';
}
/**
* 사용자 정의 key, 전화번호 가져오기, 정적 메소드여야 합니다.
* @return string
*/
public static function getMobile(): string
{
return request()->get('mobile');
}
#[RateLimiter(limit: 1, ttl: 10, key: RateLimiter::IP, message: '속도 제한', exception: RuntimeException::class)]
public function testException(): string
{
// 기본적인 초과 제한 시 발생하는 예외는 Webman\RateLimiter\RateLimitException이며, exception 매개변수로 변경할 수 있습니다.
return 'ok';
}
}
설명
- 기본 시간 간격은 1초입니다.
- ttl을 통해 시간 간격을 설정할 수 있으며, 예를 들어
ttl:60
은 60초입니다. - 기본 제한 차원은 IP 기반의 제한입니다(기본
127.0.0.1
은 제한하지 않음, 아래 구성 섹션 참조). - 내장된 IP 제한, UID 제한(요구
session('user.id')
가 비어있지 않음), SID 제한(세션 ID 기반의 제한) 기능이 있습니다. - nginx 프록시를 사용하는 경우, IP 제한 시
X-Forwarded-For
헤더를 전달해야 합니다. nginx 프록시를 참조하세요. - 초과할 경우
Webman\RateLimiter\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
인터페이스
가끔 개발자는 코드에서 직접 제한기를 호출하고 싶을 수 있습니다. 아래 코드를 참조하세요.
<?php
namespace app\controller;
use RuntimeException;
use Webman\RateLimiter\Limiter;
class UserController {
public function sendSms(string $mobile): string
{
// 여기서 mobile은 key로 사용됩니다.
Limiter::check($mobile, 5, 24*60*60, '각 전화번호는 하루에 최대 5개의 SMS를 받을 수 있습니다.');
return 'SMS 발송 성공';
}
}
구성
config/plugin/webman/rate-limiter/app.php
<?php
return [
'enable' => true,
'driver' => 'auto', // auto, apcu, memory, redis
'stores' => [
'redis' => [
'connection' => 'default',
]
],
// 이 IP의 요청은 속도 제한을 적용하지 않습니다(오직 key가 RateLimiter::IP일 때 유효합니다).
'ip_whitelist' => [
'127.0.0.1',
],
];
- enable: 제한을 활성화할지 여부
- driver:
auto
,apcu
,memory
,redis
중 하나의 값으로,auto
를 사용할 경우apcu
와memory
중 하나를 자동으로 선택합니다. - stores:
redis
구성,connection
은config/redis.php
의 대응되는key
입니다. - ip_whitelist: 화이트 리스트의 IP는 제한받지 않습니다(오직 key가
RateLimiter::IP
일 때 유효합니다).
드라이버 선택
memory
-
소개
어떠한 확장도 필요 없으며, 성능이 가장 뛰어납니다. -
사용 제한
제한은 현재 프로세스에만 유효하며, 여러 프로세스 간에 제한 데이터를 공유하지 않습니다. 또한 클러스터 제한도 지원하지 않습니다. -
적합한 사용 사례
Windows 개발 환경; 엄격하게 제한할 필요가 없는 비즈니스; CC 공격 방어 시.
apcu
-
설치 확장
apcu 확장을 설치해야 하며, php.ini에 다음과 같이 설정해야 합니다.apc.enabled=1 apc.enable_cli=1
php.ini의 위치를 모를 경우,
php --ini
명령을 통해 php.ini의 위치를 찾을 수 있습니다. -
소개
성능은 memory에 비해 약간 낮지만, 다중 프로세스로 제한 데이터를 공유할 수 있습니다. -
사용 제한
클러스터를 지원하지 않습니다. -
적합한 사용 사례
모든 개발 환경; 온라인 단일 머신 제한 환경; 클러스터에서 엄격한 제한이 필요 없는 경우; CC 공격 방어.
redis
-
의존성
redis 확장을 설치하고 Redis 구성 요소를 설치해야 합니다. 설치 명령은 다음과 같습니다.composer require -W illuminate/redis illuminate/events
-
소개
성능은 apcu보다 낮으며, 단일 머신 및 클러스터 기반의 정밀 제한을 지원합니다. -
적합한 사용 사례
개발 환경; 온라인 단일 머신 환경; 클러스터 환경