bvtterfly/sliding-window-rate-limiter
laravel的滑动窗口速率限制器
Requires
- php: ^8.0
- illuminate/contracts: ^9.0
- spatie/laravel-package-tools: ^1.9.2
Requires (Dev)
- nunomaduro/collision: ^6.0
- nunomaduro/larastan: ^2.0.1
- orchestra/testbench: ^7.0
- pestphp/pest: ^1.21
- pestphp/pest-plugin-laravel: ^1.1
- phpstan/extension-installer: ^1.1
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.0
- phpunit/phpunit: ^9.5
- predis/predis: ^1.1
Suggests
- ext-redis: Required to use the Redis PHP driver.
- predis/predis: Required when not using the Redis PHP driver (^1.1).
This package is auto-updated.
Last update: 2024-03-05 14:48:31 UTC
README
🚨 本包已废弃 🚨
我不再使用Laravel,无法证明维护此包所需的时间。因此,我选择废弃它。您可以使用我的代码进行分支并维护自己的副本。
Laravel滑动窗口速率限制器
此包提供了一种简单的方法来在指定的时间窗口内限制任何操作。您可能熟悉Laravel的速率限制器,它有类似的API,但它使用滑动窗口算法并需要Redis。
安装
您可以通过composer安装此包
composer require bvtterfly/sliding-window-rate-limiter
您可以使用以下命令发布配置文件
php artisan vendor:publish --tag="sliding-window-rate-limiter-config"
这是发布配置文件的内容
return [ 'use' => 'default', ];
该包依赖于Redis,并需要Redis连接,您可以选择使用哪个Redis连接。
用法
可以使用Bvtterfly\SlidingWindowRateLimiter\Facades\SlidingWindowRateLimiter
外观与速率限制器交互。
速率限制器提供的最简单方法是attempt
方法,该方法为给定秒数限制一个动作。该方法返回一个结果对象,指定尝试是否成功以及剩余尝试次数。如果尝试失败,您可以得到再次进行操作所需的时间。
use Bvtterfly\SlidingWindowRateLimiter\Facades\SlidingWindowRateLimiter; $result = SlidingWindowRateLimiter::attempt( 'send-message:'.$user->id, $maxAttempts = 5, $decayInSeconds = 60 ); if ($result->successful()) { // attempt is successful, do awesome thing... } else { // attempt is failed, you can get when you can retry again // use $result->retryAfter for getting the number of seconds until the action is available again // or use $result->availableAt() for getting UNIX timestamp instead. }
您可以在SlidingWindowRateLimiter
上调用以下方法
tooManyAttempts
/** * Determine if the given key has been "accessed" too many times. * * @param string $key * @param int $maxAttempts * @param int $decay * * @return bool */ public function tooManyAttempts(string $key, int $maxAttempts, int $decay = 60): bool
attempts
/** * Get the number of attempts for the given key for decay time in seconds. * * @param string $key * @param int $decay * * @return int */ public function attempts(string $key, int $decay = 60): int
resetAttempts
/** * Reset the number of attempts for the given key. * * @param string $key * * @return mixed */ public function resetAttempts(string $key): mixed
remaining
/** * Get the number of retries left for the given key. * * @param string $key * @param int $maxAttempts * @param int $decay * * @return int */ public function remaining(string $key, int $maxAttempts, int $decay = 60): int
clear
/** * Clear the number of attempts for the given key. * * @param string $key * * @return void */ public function clear(string $key)
availableIn
/** * Get the number of seconds until the "key" is accessible again. * * @param string $key * @param int $maxAttempts * @param int $decay * * @return int */ public function availableIn(string $key, int $maxAttempts, int $decay = 60): int
retriesLeft
/** * Get the number of retries left for the given key. * * @param string $key * @param int $maxAttempts * @param int $decay * * @return int */ public function retriesLeft(string $key, int $maxAttempts, int $decay = 60): int
路由速率限制
此包包含一个用于路由速率限制的throttle
中间件。它可以替换默认的Laravel throttle
中间件以使用此包的速率限制器。唯一的区别是它尝试从SlidingWindowRateLimiter
获取命名的速率限制器,或者作为后备,它将从Laravel速率限制器中获取它们。
您可能希望更改应用程序HTTP内核(App\Http\Kernel
)中的throttle
中间件的映射,以使用\Bvtterfly\SlidingWindowRateLimiter\Http\Middleware\ThrottleRequests
类。
为了使路由速率限制工作,必须为速率限制器进行配置。Laravel速率限制器包含一个基于分钟的系统工作的速率限制类(Illuminate\Cache\RateLimiting\Limit
)。但此包旨在允许基于秒的系统进行速率限制操作,因此它包含自己的速率限制器类并允许您为少于1分钟配置速率限制器。尽管如此,为了方便使用此包,它仍然支持默认的Laravel速率限制器。
定义速率限制器
SlidingWindowRateLimiter
速率限制器在很大程度上基于Laravel的速率限制器。它仅在基于秒这一点上有所不同。因此,在开始之前,请确保阅读有关Laravel文档的介绍Laravel文档。
限制配置是Bvtterfly\SlidingWindowRateLimiter\RateLimiting\Limit
类的实例,并包含一些有用的“构建器”方法,可以快速定义您的速率限制。速率限制器名称可以是您希望的任何字符串。
对于在45秒内限制500个请求
use Bvtterfly\SlidingWindowRateLimiter\RateLimiting\Limit; use Bvtterfly\SlidingWindowRateLimiter\Facades\SlidingWindowRateLimiter; /** * Configure the rate limiters for the application. * * @return void */ protected function configureRateLimiting() { SlidingWindowRateLimiter::for('global', function (Request $request) { return Limit::perSeconds(45, 500); }); }
如果传入的请求超出指定的速率限制,Laravel将自动返回一个带有429 HTTP状态码的响应。如果您希望定义速率限制器返回的响应,可以使用response
方法
SlidingWindowRateLimiter::for('global', function (Request $request) { return Limit::perSeconds(45, 500)->response(function () { return response('Custom response...', 429); }); });
您可以拥有多个速率限制。此配置将限制每30秒100个请求和每天1000个请求
SlidingWindowRateLimiter::for('global', function (Request $request) { return [ Limit::perSeconds(30, 100), Limit::perDay(1000) ]; });
传入的HTTP请求实例将传递给速率限制回调函数,速率限制可能会根据用户或请求动态计算
SlidingWindowRateLimiter::for('uploads', function (Request $request) { return $request->user()->vipCustomer() ? Limit::none() : Limit::perMinute(100); });
有时您可能希望根据某个任意值来分割速率限制。例如,您可能希望允许每个经过身份验证的用户ID每分钟访问指定路由100次请求,以及每个IP地址的访客每分钟10次请求。使用by
方法,您可以创建如下速率限制
SlidingWindowRateLimiter::for('uploads', function (Request $request) { return $request->user() ? Limit::perMinute(100)->by($request->user()->id) : Limit::perMinute(10)->by($request->ip()); });
将速率限制器附加到路由
可以使用throttle
中间件将速率限制器附加到路由或路由组。该throttle
中间件接受要分配给路由的速率限制器的名称
Route::middleware(['throttle:media'])->group(function () { Route::post('/audio', function () { // })->middleware('throttle:uploads'); Route::post('/video', function () { // })->middleware('throttle:uploads'); });
测试
composer test
变更日志
有关最近更改的更多信息,请参阅变更日志
安全漏洞
有关如何报告安全漏洞,请参阅我们的安全策略
致谢
许可证
MIT许可证(MIT)。有关更多信息,请参阅许可证文件