[英]Laravel throttle rate limiter limites access too early
我正在使用 Laravel 5.8,我想应用一个速率限制器,将发送请求限制为每分钟 500 个。
所以我尝试将这个throttle
添加到路由组中:
Route::middleware('throttle:500,1')->group(function () {
...
});
所以这意味着限制在 1 分钟内 500 个请求后访问路由。
现在的问题是我得到429 | 太多的请求太快了!
我的意思是,它似乎不会在一分钟内发送 500 个请求,但它会以某种方式限制访问。
那么这里出了什么问题? 为什么我过早收到太多请求消息?
如果您有另一个油门组,油门中间件请求会一起计算,这些会一起计算,并且该组可能会消耗您的限制
Route::get('example1', function () {
return 'ans1';
})->middleware('throttle:5,1');
Route::get('example2', function () {
return 'ans2';
})->middleware('throttle:5,1');
在上面的例子中,你有 2 个路由,但是如果你向 example1 发送 2 个请求,向 example2 发送 3 个请求,你的速率限制将对它们都完成,你得到429 | 太多请求错误。
如果您在您的组中使用多个节流中间件并且它是这样的嵌套路由:
Route::middleware('throttle:500,1')->group(function () {
Route::post('/foo', 'bar@foo')->middleware('throttle:5,60');
});
油门中间件对每个请求计数两次。 为了解决这个问题,你必须确保每条路由只有一个油门中间件。
但有时即使中间件只使用了一次,请求计数仍然是错误的。 在这种情况下,您可以制作自己的自定义油门中间件,该中间件需要一个额外的参数来命名油门键并防止重新计算请求(基于this )。
为此,您必须首先创建一个中间件(根据this ):
php artisan make:middleware CustomThrottleMiddleware
然后,将内容替换为:
<?php
namespace App\Http\Middleware;
use Closure;
use RuntimeException;
use Illuminate\Routing\Middleware\ThrottleRequests;
class CustomThrottleMiddleware extends ThrottleRequests
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param int|string $maxAttempts
* @param float|int $decayMinutes
* @param string $keyAppend
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws \Illuminate\Http\Exceptions\ThrottleRequestsException
*/
public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1, $keyAppend = '')
{
$key = $this->resolveRequestSignature($request, $keyAppend);
$maxAttempts = $this->resolveMaxAttempts($request, $maxAttempts);
if ($this->limiter->tooManyAttempts($key, $maxAttempts)) {
throw $this->buildException($key, $maxAttempts);
}
$this->limiter->hit($key, $decayMinutes * 60);
$response = $next($request);
return $this->addHeaders(
$response, $maxAttempts,
$this->calculateRemainingAttempts($key, $maxAttempts)
);
}
/**
* Resolve request signature.
*
* @param \Illuminate\Http\Request $request
* @param string $keyAppend
* @return string
*
* @throws \RuntimeException
*/
protected function resolveRequestSignature($request, $keyAppend='')
{
if ($user = $request->user()) {
return sha1($user->getAuthIdentifier().$keyAppend);
}
if ($route = $request->route()) {
return sha1($route->getDomain().'|'.$request->ip().$keyAppend);
}
throw new RuntimeException('Unable to generate the request signature. Route unavailable.');
}
}
这样做之后,您必须通过更新app/Http/Kernel.php
文件来注册中间件:
protected $routeMiddleware = [
//...
'custom_throttle' => \App\Http\Middleware\CustomThrottleMiddleware::class,
];
现在你可以在你的路线中使用这个新的定制油门中间件,就像这样:
Route::middleware('throttle:500,1')->group(function () {
Route::post('/foo', 'bar@foo')->middleware('custom_throttle:5,60,foo');
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.