搜索

首页  >  问答  >  正文

仅成功请求的速率限制 (Laravel 9)

是否有办法对路线应用速率限制,但仅限于成功响应。例如,如果用户向 send/code 端点发送请求 5 次,如果全部成功,则阻止用户再次发送请求。但是,如果其中 2 次失败(例如验证错误或其他问题),但 3 次成功,则用户应该在给定时间内再尝试 2 次。

我知道在执行请求之前进行速率限制检查,然后阻止或让用户继续。但是有没有办法应用我的逻辑,或者我应该尝试不同的方法?

P粉807239416P粉807239416433 天前569

全部回复(2)我来回复

  • 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。

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

    回复
    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>

    回复
    0
  • 取消回复