頻率限制

簡介

Laravel 中內建了一個簡單易用的頻率限制抽象功能,該功能會與專案的 搭配使用,讓我們能輕鬆限制指定時間內任何動作的頻率。

lightbulb

若想對連入 HTTP Request 的頻率限制,請參考 Rate Limiter Middleware 的說明文件

快取設定

一般來說,Rate Limiter 會使用專案中 cache 設定檔 default 索引鍵上所定義的預設快取。不過,我們可以在專案的 cache 設定檔中定義 limiter 索引鍵來指定 Rate Limiter 要使用哪個快取 Driver:

1'default' => 'memcached',
2 
3'limiter' => 'redis',
1'default' => 'memcached',
2 
3'limiter' => 'redis',

基礎用法

可通過 Illuminate\Support\Facades\RateLimiter Facade 來使用 Rate Limiter。Rate Limiter 所提供的最簡單的方法是 attempt 方法,該方法會對給定閉包以給定秒數來做頻率限制。

若該回呼已無法再嘗試,則 attempt 方法會回傳 false。若還能繼續嘗試,則 attempt 會回傳該回呼的執行結果或 trueattempt 方法的第一個引數為 Rate Limiter 的「索引鍵」,索引鍵可以是任意字串,用來表示要被頻率限制的動作:

1use Illuminate\Support\Facades\RateLimiter;
2 
3$executed = RateLimiter::attempt(
4 'send-message:'.$user->id,
5 $perMinute = 5,
6 function() {
7 // 傳送訊息...
8 }
9);
10 
11if (! $executed) {
12 return 'Too many messages sent!';
13}
1use Illuminate\Support\Facades\RateLimiter;
2 
3$executed = RateLimiter::attempt(
4 'send-message:'.$user->id,
5 $perMinute = 5,
6 function() {
7 // 傳送訊息...
8 }
9);
10 
11if (! $executed) {
12 return 'Too many messages sent!';
13}

如有需要,可以為 attempt 方法提供第四個「Decay Rate」引數,或是直到頻率限制被重設前的秒數。例如,我們可以將上面的範例改為每 2 分鐘允許 5 次嘗試:

1$executed = RateLimiter::attempt(
2 'send-message:'.$user->id,
3 $perTwoMinutes = 5,
4 function() {
5 // 傳送訊息...
6 },
7 $decayRate = 120,
8);
1$executed = RateLimiter::attempt(
2 'send-message:'.$user->id,
3 $perTwoMinutes = 5,
4 function() {
5 // 傳送訊息...
6 },
7 $decayRate = 120,
8);

手動增加嘗試次數

若想手動使用 Rate Limiter,則還有其他許多能使用的方法。舉例來說,我們可以叫用 tooManyAttempts 方法來判斷給定的 Rate Limiter 索引鍵是否已遇到其每分鐘所允許的最大嘗試次數:

1use Illuminate\Support\Facades\RateLimiter;
2 
3if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) {
4 return 'Too many attempts!';
5}
6 
7RateLimiter::hit('send-message:'.$user->id);
8 
9// 傳送訊息...
1use Illuminate\Support\Facades\RateLimiter;
2 
3if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) {
4 return 'Too many attempts!';
5}
6 
7RateLimiter::hit('send-message:'.$user->id);
8 
9// 傳送訊息...

或者,也可以使用 remaining 方法來取得給定索引鍵剩下的嘗試次數。若給定的索引鍵還有可嘗試的次數,則可叫用 hit 方法來增加總嘗試次數:

1use Illuminate\Support\Facades\RateLimiter;
2 
3if (RateLimiter::remaining('send-message:'.$user->id, $perMinute = 5)) {
4 RateLimiter::hit('send-message:'.$user->id);
5 
6 // 傳送訊息...
7}
1use Illuminate\Support\Facades\RateLimiter;
2 
3if (RateLimiter::remaining('send-message:'.$user->id, $perMinute = 5)) {
4 RateLimiter::hit('send-message:'.$user->id);
5 
6 // 傳送訊息...
7}

判斷 Limiter 是否可用

若某個索引鍵已無可用的嘗試次數,則 availableIn 方法會回傳距離下次可獲得嘗試次數的剩餘秒數:

1use Illuminate\Support\Facades\RateLimiter;
2 
3if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) {
4 $seconds = RateLimiter::availableIn('send-message:'.$user->id);
5 
6 return 'You may try again in '.$seconds.' seconds.';
7}
8 
9RateLimiter::hit('send-message:'.$user->id);
10 
11// 傳送訊息...
1use Illuminate\Support\Facades\RateLimiter;
2 
3if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) {
4 $seconds = RateLimiter::availableIn('send-message:'.$user->id);
5 
6 return 'You may try again in '.$seconds.' seconds.';
7}
8 
9RateLimiter::hit('send-message:'.$user->id);
10 
11// 傳送訊息...

清除嘗試次數

可使用 clear 方法來重設給定 Rate Limiter 索引鍵的嘗試次數。舉例來說,我們可以在收件人已閱讀某個訊息後重設嘗試次數:

1use App\Models\Message;
2use Illuminate\Support\Facades\RateLimiter;
3 
4/**
5 * Mark the message as read.
6 */
7public function read(Message $message): Message
8{
9 $message->markAsRead();
10 
11 RateLimiter::clear('send-message:'.$message->user_id);
12 
13 return $message;
14}
1use App\Models\Message;
2use Illuminate\Support\Facades\RateLimiter;
3 
4/**
5 * Mark the message as read.
6 */
7public function read(Message $message): Message
8{
9 $message->markAsRead();
10 
11 RateLimiter::clear('send-message:'.$message->user_id);
12 
13 return $message;
14}
翻譯進度
100% 已翻譯
更新時間:
2024年6月30日 上午8:27:00 [世界標準時間]
翻譯人員:
  • cornch
幫我們翻譯此頁

留言

尚無留言

“Laravel” is a Trademark of Taylor Otwell.
The source documentation is released under MIT license. See laravel/docs on GitHub for details.
The translated documentations are released under MIT license. See cornch/laravel-docs-l10n on GitHub for details.