Skip to content

速率限制

介绍

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

lightbulb

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

缓存配置

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

php
'default' => 'memcached',

'limiter' => 'redis',

基本用法

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

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

php
use Illuminate\Support\Facades\RateLimiter;

$executed = RateLimiter::attempt(
    'send-message:'.$user->id,
    $perMinute = 5,
    function() {
        // 发送消息...
    }
);

if (! $executed) {
  return '发送的消息太多!';
}

手动增加尝试次数

如果您希望手动与速率限制器交互,可以使用多种其他方法。例如,您可以调用 tooManyAttempts 方法来确定给定的速率限制器键是否已超过每分钟允许的最大尝试次数:

php
use Illuminate\Support\Facades\RateLimiter;

if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) {
    return '尝试次数过多!';
}

或者,您可以使用 remaining 方法来检索给定键的剩余尝试次数。如果给定键还有重试次数,您可以调用 hit 方法来增加总尝试次数:

php
use Illuminate\Support\Facades\RateLimiter;

if (RateLimiter::remaining('send-message:'.$user->id, $perMinute = 5)) {
    RateLimiter::hit('send-message:'.$user->id);

    // 发送消息...
}

确定限制器的可用性

当一个键没有更多尝试次数时,availableIn 方法返回直到更多尝试可用的剩余秒数:

php
use Illuminate\Support\Facades\RateLimiter;

if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) {
    $seconds = RateLimiter::availableIn('send-message:'.$user->id);

    return '您可以在 '.$seconds.' 秒后重试。';
}

清除尝试次数

您可以使用 clear 方法重置给定速率限制器键的尝试次数。例如,您可以在接收者读取给定消息时重置尝试次数:

php
use App\Models\Message;
use Illuminate\Support\Facades\RateLimiter;

/**
 * 将消息标记为已读。
 *
 * @param  \App\Models\Message  $message
 * @return \App\Models\Message
 */
public function read(Message $message)
{
    $message->markAsRead();

    RateLimiter::clear('send-message:'.$message->user_id);

    return $message;
}