Ben*_*rey 1 php throttling rate-limiting redis laravel
Laravel 开箱即用地提供了两个可用于速率限制(节流)的中间件:
\Illuminate\Routing\Middleware\ThrottleRequests::class
\Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class
Run Code Online (Sandbox Code Playgroud)
正如文档所述,如果您使用 Redis 作为缓存驱动程序,您可以像这样更改映射Kernel.php:
/**
* The application's middleware aliases.
*
* Aliases may be used instead of class names to conveniently assign middleware to routes and groups.
*
* @var array<string, class-string|string>
*/
protected $middlewareAliases = [
// ...
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class
// ...
];
Run Code Online (Sandbox Code Playgroud)
问题是上述内容不是动态的,依赖于环境。例如,在我的staging环境production中,我使用 Redis,但在我的local环境中development,我不使用 Redis。
有一个明显的脏修复,如下所示(Kernel.php):
/**
* The application's middleware aliases.
*
* Aliases may be used instead of class names to conveniently assign middleware to routes and groups.
*
* @var array<string, class-string|string>
*/
protected $middlewareAliases = [
// ...
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class
// ...
];
/**
* Create a new HTTP kernel instance.
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @param \Illuminate\Routing\Router $router
* @return void
*/
public function __construct(Application $app, Router $router)
{
if ($app->environment('production')) {
$this->middlewareAliases['throttle'] = \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class;
}
parent::__construct($app, $router);
}
Run Code Online (Sandbox Code Playgroud)
是否有一种“标准”方法可以实现此目的而无需重写Kernel构造函数?本质上,我希望我的应用程序根据环境是否设置为production(或者默认缓存存储设置为redis)来动态选择相关的中间件。
上述解决方案不起作用,因为在引导应用程序之前访问内核,因此此时环境不可用。我现在正在研究的另一个解决方案是扩展基ThrottleRequests类,以便动态调用相关类。
经过大量研究和测试,我得出的结论是,最好的解决方案是动态设置throttle中间件,如下所示RouteServiceProvider:
class RouteServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot(): void
{
$this->registerThrottleMiddleware();
}
/**
* Register the middleware used for throttling requests.
*
* @return void
*/
private function registerThrottleMiddleware(): void
{
$router = app()->make('router');
$middleware = config('cache.default') !== 'redis'
? \Illuminate\Routing\Middleware\ThrottleRequests::class
: \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class;
$router->aliasMiddleware('throttle', $middleware);
}
}
Run Code Online (Sandbox Code Playgroud)