速率限制
简介
Laravel 包含一个易于使用的速率限制抽象,它与应用程序的缓存结合使用,可以轻松限制在指定时间窗口内的任何操作。
如果您对限制传入的 HTTP 请求感兴趣,请查阅速率限制器中间件文档。
缓存配置
通常,速率限制器使用您的默认应用程序缓存,该缓存由应用程序缓存配置文件中的 default
键定义。但是,您可以通过在应用程序的缓存配置文件中定义 limiter
键来指定速率限制器应使用的缓存驱动程序
1'default' => env('CACHE_STORE', 'database'),2 3'limiter' => 'redis',
基本用法
可以使用 Illuminate\Support\Facades\RateLimiter
facade 与速率限制器进行交互。速率限制器提供的最简单方法是 attempt
方法,该方法在给定的秒数内限制给定回调的速率。
当回调没有剩余尝试次数时,attempt
方法返回 false
;否则,attempt
方法将返回回调的结果或 true
。attempt
方法接受的第一个参数是速率限制器“键”,它可以是您选择的任何字符串,表示正在速率限制的操作
1use Illuminate\Support\Facades\RateLimiter; 2 3$executed = RateLimiter::attempt( 4 'send-message:'.$user->id, 5 $perMinute = 5, 6 function() { 7 // Send message... 8 } 9);10 11if (! $executed) {12 return 'Too many messages sent!';13}
如果需要,您可以为 attempt
方法提供第四个参数,即“衰减率”,或可用尝试次数重置之前的秒数。例如,我们可以修改上面的示例,以允许每两分钟尝试五次
1$executed = RateLimiter::attempt(2 'send-message:'.$user->id,3 $perTwoMinutes = 5,4 function() {5 // Send message...6 },7 $decayRate = 120,8);
手动增加尝试次数
如果您想手动与速率限制器进行交互,可以使用各种其他方法。例如,您可以调用 tooManyAttempts
方法来确定给定的速率限制器键是否已超过每分钟允许的最大尝试次数
1use Illuminate\Support\Facades\RateLimiter;2 3if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) {4 return 'Too many attempts!';5}6 7RateLimiter::increment('send-message:'.$user->id);8 9// Send message...
或者,您可以使用 remaining
方法检索给定键的剩余尝试次数。如果给定键还有剩余重试次数,您可以调用 increment
方法来增加总尝试次数
1use Illuminate\Support\Facades\RateLimiter;2 3if (RateLimiter::remaining('send-message:'.$user->id, $perMinute = 5)) {4 RateLimiter::increment('send-message:'.$user->id);5 6 // Send message...7}
如果您想将给定速率限制器键的值增加超过 1,您可以将所需的数量提供给 increment
方法
1RateLimiter::increment('send-message:'.$user->id, amount: 5);
确定限制器可用性
当一个键没有更多剩余尝试次数时,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::increment('send-message:'.$user->id);10 11// Send message...
清除尝试次数
您可以使用 clear
方法重置给定速率限制器键的尝试次数。例如,您可以在接收者读取给定消息时重置尝试次数
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}