速率限制
简介
Laravel包含一个易于使用的速率限制抽象,它与应用程序的缓存结合使用,提供了一种简单的方法来限制特定时间段内的任何操作。
如果您对限制传入的HTTP请求感兴趣,请参阅速率限制中间件文档。
缓存配置
通常,速率限制器使用应用程序的默认缓存,该缓存由应用程序的cache
配置文件中的default
键定义。但是,您可以通过在应用程序的cache
配置文件中定义limiter
键来指定速率限制器应使用的缓存驱动程序。
'default' => env('CACHE_STORE', 'database'), 'limiter' => 'redis',
基本用法
可以使用Illuminate\Support\Facades\RateLimiter
外观与速率限制器进行交互。速率限制器提供的最简单的方法是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,);
手动增加尝试次数
如果您想手动与速率限制器交互,则可以使用各种其他方法。例如,您可以调用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;}