跳至内容

速率限制

简介

Laravel 包含一个易于使用的速率限制抽象,它与应用程序的 缓存 结合使用,提供了一种简单的方法来限制指定时间窗口内发生的任何操作。

lightbulb

如果你有兴趣限制传入 HTTP 请求的速率,请查阅 速率限制中间件文档

缓存配置

通常,速率限制器使用你的应用程序的默认缓存,该缓存由应用程序的 cache 配置文件中的 default 键定义。但是,你可以在应用程序的 cache 配置文件中定义 limiter 键来指定速率限制器应使用哪个缓存驱动程序。

'default' => env('CACHE_STORE', 'database'),
 
'limiter' => 'redis',

基本用法

可以使用 Illuminate\Support\Facades\RateLimiter 外观与速率限制器进行交互。速率限制器提供的最简单的方法是 attempt 方法,该方法在指定秒数内限制给定回调的速率。

当回调没有剩余的尝试次数时,attempt 方法返回 false;否则,attempt 方法将返回回调的结果或 trueattempt 方法接受的第一个参数是速率限制器“键”,它可以是你选择的任何字符串,表示要限制速率的操作。

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...
}

如果你想将给定速率限制器键的值增加超过 1,则可以向 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;
}