簡體   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