Heim  >  Fragen und Antworten  >  Hauptteil

Ratenbegrenzung nur für erfolgreiche Anfragen (Laravel 9)

Gibt es eine Möglichkeit, eine Ratenbegrenzung auf eine Route anzuwenden, jedoch nur bei erfolgreichen Antworten. Wenn der Benutzer beispielsweise fünfmal eine Anfrage an den send/code-Endpunkt sendet und alle erfolgreich sind, wird der Benutzer daran gehindert, die Anfrage erneut zu senden. Wenn jedoch zwei davon fehlschlagen (z. B. ein Validierungsfehler oder ein anderes Problem), drei jedoch erfolgreich sind, sollte der Benutzer es innerhalb der vorgegebenen Zeit noch zweimal versuchen.

Ich weiß, dass man vor der Ausführung der Anfrage eine Überprüfung des Ratenlimits durchführen und den Benutzer dann blockieren oder weitermachen lassen kann. Aber gibt es eine Möglichkeit, meine Logik anzuwenden, oder sollte ich einen anderen Ansatz ausprobieren?

P粉807239416P粉807239416311 Tage vor475

Antworte allen(2)Ich werde antworten

  • P粉986937457

    P粉9869374572024-01-06 17:02:10

    这是源代码

    use Illuminate\Support\Facades\RateLimiter;
    
    class CodeZiDotProTestRateLimit extends Controller{
    public function test_rate_limit_only_success(Request $request){
    
        // Step 1: Validate the request data
        $validator = Validator::make($request->all(), [
            'name' => 'required|string',
            'email' => 'required|email',
            'password' => 'required|min:8',
        ]);
    
        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()], 422);
        }
    
        // Step 2: Apply rate limiting to this controller action
        $key = 'test_rate_limit_only_success_by_ip_'.request()->ip();
        if (RateLimiter::tooManyAttempts($key,10)) {
            return response()->json(['errors' => 'You have made too much in a short time. Please wait after 1 minute'], 422);
        } else {
            RateLimiter::hit($key, 60);
        }
    }

    }

    假设我的网址是 Example.com/test_Rate_Limit_only_success。

    在此示例中,当用户向系统发送请求时,应用程序仍会验证该请求(如果出现错误,用户将发送无限制的请求)。在数据有效的情况下,限速部分将开始工作。

    Antwort
    0
  • P粉512526720

    P粉5125267202024-01-06 09:10:49

    您可能需要制作自己的中间件,但您可以扩展 ThrottleRequests 类并自定义您想要处理响应的方式:

    <?php
    
    namespace App\Http\Middleware;
    
    use Closure;
    use Illuminate\Routing\Middleware\ThrottleRequests;
    use Illuminate\Support\Arr;
    
    class ThrottleSuccess extends ThrottleRequests
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @param  array  $limits
         * @return \Symfony\Component\HttpFoundation\Response
         *
         * @throws \Illuminate\Http\Exceptions\ThrottleRequestsException
         */
        protected function handleRequest($request, Closure $next, array $limits)
        {
            $response = $next($request); // call the controller first
    
            if ($response->statusCode === 200) { // only hit limiter on successful response
                foreach ($limits as $limit) {
                    if ($this->limiter->tooManyAttempts($limit->key, $limit->maxAttempts)) {
                        throw $this->buildException($request, $limit->key, $limit->maxAttempts, $limit->responseCallback);
                    }
        
                    $this->limiter->hit($limit->key, $limit->decayMinutes * 60);
                }
            }
    
            foreach ($limits as $limit) {
                $response = $this->addHeaders(
                    $response,
                    $limit->maxAttempts,
                    $this->calculateRemainingAttempts($limit->key, $limit->maxAttempts)
                );
            }
    
            return $response;
        }
    }
    
    

    然后将您的中间件添加到Kernel.php

        protected $routeMiddleware = [
            // ...
            'throttle.success' => ThrottleSuccess::class,
            // ...
        ];
    

    然后像原来的throttle中间件一样在路由中使用它:

    Route::middleware('throttle.success:5,1')->group(function () {
        // ...
    });
    

    注意:如果您想返回从 RateLimiter::for 构建的自定义响应,您可能必须重写 handleRequestUsingNamedLimiter,我在这里没有为此做任何事情。< /p>

    Antwort
    0
  • StornierenAntwort