仅在 Laravel 生产环境中使用 Redis 进行限制

问题描述 投票:0回答:2

背景

Laravel 开箱即用地提供了两个可用于速率限制(节流)的中间件:

\Illuminate\Routing\Middleware\ThrottleRequests::class
\Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class

正如文档所述,如果您使用 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
    // ...
];

问题

问题是上述内容不是动态的,依赖于环境。例如,在我的

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); }
是否有一种“标准”方法可以实现此目的,而无需重写 

Kernel

 构造函数?本质上,我希望我的应用程序根据环境是否设置为
production
(或者默认缓存存储设置为
redis
)来动态选择相关中间件。

更新

上述解决方案不起作用,因为在引导应用程序之前访问内核,因此此时环境不可用。我现在正在研究的另一个解决方案是扩展基本

ThrottleRequests

 类,以便动态调用相关类。

php laravel redis throttling rate-limiting
2个回答
5
投票
经过大量研究和测试,我得出的结论是,最好的解决方案是在

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); } }
    

0
投票
在 Laravel 11 上,您需要在

throttleWithRedis()

 上使用 
bootstrap/app.php
 助手。如下图:

return Application::configure(basePath: dirname(__DIR__)) ->withRouting( web: __DIR__ . '/../routes/web.php', api: __DIR__ . '/../routes/api.php', commands: __DIR__ . '/../routes/console.php', ) ->withMiddleware(function (Middleware $middleware) { $middleware->throttleWithRedis(); })
    
© www.soinside.com 2019 - 2024. All rights reserved.