我为登录创建了一个速率限制器,它将请求限制为每 10 分钟
n
次。如果请求已达到速率限制,我想返回一个验证异常,通知清除速率限制器之前的剩余时间。
为了简单起见,我将限制设置为
2
,如下:
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
RateLimiter::for('login', function (Request $request) {
$email = (string) $request->email;
$throttle_key = str($email)->ascii()->lower().'|'.$request->ip();
return Limit::perMinutes(10, 2)
->by($throttle_key)
->response(function () use ($throttle_key) {
$seconds = RateLimiter::availableIn($throttle_key);
throw ValidationException::withMessages([
'email' => trans('auth.throttle', [
'seconds' => $seconds
]),
]);
});
});
上面的代码正确地限制了请求:用户在 10 分钟内只有 2 次尝试尝试使用他们的电子邮件登录。但是,
RateLimiter::availableIn($throttle_key)
没有给出我上面提到的正确值。
当我第三次尝试错误登录时,
RateLimiter::availableIn($throttle_key)
只给出 1-60,而不是剩余 1 到 600 秒之间的值。经过第一分钟的衰减时间后,它总是显示 0
秒剩余,但速率限制器仍然在接下来的 9 分钟内保持请求。
请分享您想到的任何建议。非常感谢您的帮助。
我遇到了同样的问题,我无法评论导致新帐户,但我进行了修改并且在门面来自的
Illuminate\Cache\RateLimiter
类中做了一些转储,
显然它用一些奇怪的名字将它存储在缓存中,例如我的密钥是
'1'
并且它以加密方式将它存储在缓存中,例如'sdkf34kfshsf:timer'
,并通过方法访问它availableIn
是仅将'1'
传递给缓存而不是加密值。
编辑----------------:
1 我发现的解决方法是使用标头中的值来计算剩余时间。
在响应方法的回调函数中添加headers数组。
->response(function(Request $request,array $headers) {
在“秒”行
'seconds' => $headers['Retry-After']
或
'seconds' => $headers['X-RateLimit-Reset'] - time()
差值应该提供剩余的秒数