如何使用不同 ips 的参数限制路由

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

我创建了一个与 laravel throttle 一起使用的页面访问功能。每个 ip/用户可以每 60 分钟增加一次访问计数器。 我有一个问题,无法在不同的 ID 上应用节流阀,并且节流阀每 60 分钟仅在路线上工作 1 次并且不关心 ID: (/home/visit/3 , /home/visit/4 ,.....): 每 60 分钟 1 次

路线.php:

Route::post('/home/visit/{id}',[HomeController::class,'counter_visit'])->middleware('throttle:visit');

RouteServiceProvider.php

            RateLimiter::for('visit', function (Request $request) {
            return $request->user()
                ? Limit::perHour(1)->by($request->user()->id)
                : Limit::perHour(1)->by($request->ip());
                });

我怎样才能像下面那样为每个 id 应用限制?

/home/visit/3 : 每 60 分钟 1 次 /home/visit/4 :每 60 分钟 1 次

感谢您的帮助

laravel throttling
1个回答
1
投票

目前,您正在使用 Laravel 内置的 throttle 中间件,它限制每个用户或 IP 地址对给定路由的请求数量,而不管 ID 参数。要实现基于 ID 参数的节流,需要定义自己的自定义中间件。

这是一个示例,说明如何创建自定义中间件,根据 ID 限制请求:

  1. 通过在终端中运行以下命令来创建一个新的中间件类:

php artisan make:middleware ThrottleById

  1. 打开新建的ThrottleById中间件类,修改handle()方法,加入如下代码:

    使用 Illuminate\Cache\RateLimiter;

    使用 Symfony\Component\HttpFoundation\Response;

    使用 Illuminate\Http\Exceptions\ThrottleRequestsException;

    公共函数句柄($request, Closure $next, $maxAttempts = 1, $decayMinutes = 60)

    {

    $limiter = app(RateLimiter::class)->for('visit_'.$request->route('id'), $maxAttempts, $decayMinutes);

    if ($limiter->tooManyAttempts($request)) {

    $retryAfter = $limiter->availableIn($request);

    抛出新的 ThrottleRequestsException(null, $retryAfter, [

    'Retry-After' => $retryAfter,

    'X-RateLimit-Limit' => $maxAttempts,

    'X-RateLimit-剩余'=> 0,

    ]);

    }

     $limiter->hit($request);
    
     $response = $next($request);
    
     $response->headers->add([
         'X-RateLimit-Limit' => $maxAttempts,
         'X-RateLimit-Remaining' => $limiter->retriesLeft($request),
         'X-RateLimit-Reset' => $limiter->availableAt($request),
     ]);
    
     return $response;
    

    }

以上代码是Laravel内置节流中间件的实现,只是修改为使用请求的ID参数为每个ID创建唯一的缓存键。

  1. 接下来在App\Http\Kernel类中的$routeMiddleware数组中注册中间件:

    protected $routeMiddleware = [ // ... 'throttle_by_id' => \App\Http\Middleware\ThrottleById::class, ];

  2. 最后,将新的中间件应用到您的路由定义中,如下所示:

    Route::post('/home/visit/{id}', [HomeController::class, 'counter_visit'])->middleware('throttle_by_id');

© www.soinside.com 2019 - 2024. All rights reserved.