Laravel : Increase time on second time login attem

2020-07-09 07:14发布

Currently five login attempts blocks user for 1 minute and its working fine with the following code :

if ($this->hasTooManyLoginAttempts($request)) {
    $this->fireLockoutEvent($request);
    return $this->sendLockoutResponse($request);
}

What i want is that, When a user gets unblocked again after the first attempts, On the second attempts the block time should increase to 3 minutes.

I searched around, But could not found anything, Is there any way around it ?

3条回答
做自己的国王
2楼-- · 2020-07-09 07:37

I think you need to set property in LoginController:

public $decayMinutes = 1; // minutes to lockout

Also you can controll numbers of attempts:

public $maxAttempts = 5;

For more information you can investigate: trait AuthenticatesUsers - which has method "login" and code from your description. And this trait uses another trait: "ThrottlesLogins" -> this traits has method named "decayMinutes". It returns number of minutes.

Hope it will help you!

查看更多
劫难
3楼-- · 2020-07-09 08:00

I would suggest you try the following code. Please ask if anything is unclear.

$minutes = 3;
$key = $this->throttleKey($request);
$rateLimiter = $this->limiter();

if ($this->hasTooManyLoginAttempts($request)) {

    $attempts = $rateLimiter->attempts($key); 
    if ($attempts > 1) {
        $attempts === 2 && $rateLimiter->clear($key);
        $this->decayMinutes = ($attempts - 1) * $minutes;
        $attempts === 2 && $this->incrementLoginAttempts($request);
        $this->incrementLoginAttempts($request);
    }

    $this->fireLockoutEvent($request);
    return $this->sendLockoutResponse($request);
}

Code for incremental blocking:

$minutes = 3;
$key = $this->throttleKey($request);
$rateLimiter = $this->limiter();

if ($this->hasTooManyLoginAttempts($request)) {

    $attempts = $rateLimiter->attempts($key);
    $rateLimiter->clear($key);
    $this->decayMinutes = $attempts === 1 ? 1 : ($attempts - 1) * $minutes;

    for ($i = 0; $i < $attempts; $i++) {
        $this->incrementLoginAttempts($request);
    }

    $this->fireLockoutEvent($request);
    return $this->sendLockoutResponse($request);
}

Code for incremental blocking with cache:

$minutes = 3;
$key = $this->throttleKey($request);
$rateLimiter = $this->limiter();

if ($this->hasTooManyLoginAttempts($request)) {

    $attempts = $rateLimiter->attempts($key);
    $rateLimiter->clear($key); // might have to add logic here

    $reflection = new \ReflectionClass($rateLimiter);
    $property = $reflection->getProperty('cache');
    $property->setAccessible(true);
    $cache = $property->getValue($rateLimiter);
    $reflectionMethod = new \ReflectionMethod($rateLimiter, 'availableAt');
    $reflectionMethod->setAccessible(true);

    $blockMinutes = $attempts === 1 ? 1 : $attempts > 1 ? ($attempts - 1) * $minutes : 1;
    $cache->add($key.':timer', $reflectionMethod->invoke($rateLimiter, $blockMinutes * 60), $blockMinutes);
    $added = $cache->add($key, 0, $blockMinutes);
    $hits = (int) $cache->increment($key, $attempts);
    if (! $added && $hits === 1) {
        $cache->put($key, 1, $blockMinutes);
    }

    $reflectionMethod->setAccessible(false);
    $property->setAccessible(false);

    $this->fireLockoutEvent($request);
    return $this->sendLockoutResponse($request);
}
查看更多
该账号已被封号
4楼-- · 2020-07-09 08:02

I think laravel default doesn't provide what your need, So you need to save in (cache, session or database) if user had blocked once on your own, and increase decayMinutes as you want.

if ($this->hasTooManyLoginAttempts($request)) {
    if(Cache::has($this->throttleKey($request))){
        $this->decayMinutes = 3;
    }

    Cache::put($this->throttleKey($request), true);
    $this->fireLockoutEvent($request);

    return $this->sendLockoutResponse($request);
}
查看更多
登录 后发表回答