是否有办法对路线应用速率限制,但仅限于成功响应。例如,如果用户向 send/code
端点发送请求 5 次,如果全部成功,则阻止用户再次发送请求。但是,如果其中 2 次失败(例如验证错误或其他问题),但 3 次成功,则用户应该在给定时间内再尝试 2 次。
我知道在执行请求之前进行速率限制检查,然后阻止或让用户继续。但是有没有办法应用我的逻辑,或者我应该尝试不同的方法?
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。
在此示例中,当用户向系统发送请求时,应用程序仍会验证该请求(如果出现错误,用户将发送无限制的请求)。在数据有效的情况下,限速部分将开始工作。
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>