繁体   English   中英

Laravel 油门速率限制器过早限制访问

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM