Laravel 包含一个简单易用的速率限制抽象,它与你的应用程序的 缓存 结合使用,提供了一种在指定时间窗口内限制任何操作的简便方法。
[!注意]
如果您对限制传入的 HTTP 请求感兴趣,请查阅限流中间件文档。
通常, 速率限制器会利用你的默认应用缓存, 该缓存由你的应用的 cache 配置文件中的 default 键定义。 但是, 你可以通过在你的应用的 cache 配置文件中定义一个 limiter 键来指定速率限制器应该使用哪个缓存驱动程序:
'default' => env('CACHE_STORE', 'database'),
'limiter' => 'redis', // [tl! add]Illuminate\Support\Facades\RateLimiter 外观可用于与限速器交互。限速器提供的最简单方法是 attempt 方法,它会在给定的秒数内对给定的回调进行限速。
attempt 方法在回调没有剩余可用尝试次数时返回 false;否则,attempt 方法将返回回调的结果或 true。attempt 方法接受的第一个参数是一个限速器"key",它可以是您选择的任何字符串,代表正在进行限速的操作:
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,
);如果需要手动与限速器交互,还有其他多种方法可用。例如,你可以调用 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);当某个键已无剩余尝试次数时, 该 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...您可以使用 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;
}