簡介 (Introduction)
Laravel 包含一個簡單易用的速率限制抽象層,它結合你的應用程式的 快取,提供了一種簡單的方法來限制在指定時間視窗內的任何動作。
[!NOTE] 如果你對限制傳入 HTTP 請求的速率感興趣,請參閱 速率限制器 middleware 文件。
快取設定 (Cache Configuration)
通常,速率限制器會使用你的應用程式的 cache 設定檔中 default 鍵定義的預設應用程式快取。但是,你可以透過在應用程式的 cache 設定檔中定義 limiter 鍵來指定速率限制器應使用哪個快取驅動程式:
'default' => env('CACHE_STORE', 'database'),
'limiter' => 'redis', // [tl! add]
基本用法 (Basic Usage)
Illuminate\Support\Facades\RateLimiter facade 可用於與速率限制器互動。速率限制器提供的最簡單方法是 attempt 方法,它會在給定秒數內對給定的回呼進行速率限制。
當回呼沒有剩餘的嘗試次數時,attempt 方法會傳回 false;否則,attempt 方法將傳回回呼的結果或 true。attempt 方法接受的第一個參數是速率限制器「鍵」,它可以是你選擇的任何字串,代表正在進行速率限制的動作:
use Illuminate\Support\Facades\RateLimiter;
$executed = RateLimiter::attempt(
'send-message:'.$user->id,
$perMinute = 5,
function() {
// Send message...
}
);
if (! $executed) {
return 'Too many messages sent!';
}
如果需要,你可以向 attempt 方法提供第四個參數,即「衰減率」,或直到可用嘗試次數重置的秒數。例如,我們可以修改上面的範例,允許每兩分鐘五次嘗試:
$executed = RateLimiter::attempt(
'send-message:'.$user->id,
$perTwoMinutes = 5,
function() {
// Send message...
},
$decayRate = 120,
);
手動遞增嘗試次數 (Manually Incrementing Attempts)
如果你想手動與速率限制器互動,還有多種其他方法可用。例如,你可以呼叫 tooManyAttempts 方法來確定給定的速率限制器鍵是否已超過其每分鐘允許的最大嘗試次數:
use Illuminate\Support\Facades\RateLimiter;
if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) {
return 'Too many attempts!';
}
RateLimiter::increment('send-message:'.$user->id);
// Send message...
或者,你可以使用 remaining 方法來擷取給定鍵的剩餘嘗試次數。如果給定鍵還有剩餘的重試次數,你可以呼叫 increment 方法來遞增總嘗試次數:
use Illuminate\Support\Facades\RateLimiter;
if (RateLimiter::remaining('send-message:'.$user->id, $perMinute = 5)) {
RateLimiter::increment('send-message:'.$user->id);
// Send message...
}
如果你想將給定速率限制器鍵的值遞增超過一,你可以向 increment 方法提供所需的數量:
RateLimiter::increment('send-message:'.$user->id, amount: 5);
判斷限制器可用性 (Determining Limiter Availability)
當一個鍵沒有剩餘嘗試次數時,availableIn 方法會傳回直到有更多嘗試次數可用為止的剩餘秒數:
use Illuminate\Support\Facades\RateLimiter;
if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) {
$seconds = RateLimiter::availableIn('send-message:'.$user->id);
return 'You may try again in '.$seconds.' seconds.';
}
RateLimiter::increment('send-message:'.$user->id);
// Send message...
清除嘗試次數 (Clearing Attempts)
你可以使用 clear 方法重置給定速率限制器鍵的嘗試次數。例如,當收件者閱讀給定訊息時,你可以重置嘗試次數:
use App\Models\Message;
use Illuminate\Support\Facades\RateLimiter;
/**
* Mark the message as read.
*/
public function read(Message $message): Message
{
$message->markAsRead();
RateLimiter::clear('send-message:'.$message->user_id);
return $message;
}