iT邦幫忙

0

Laravel 登入失敗次數限制 等待時間遞增

Laravel 本身已實現了登入失敗次數限制的功能。在使用 Laravel 的登入驗證時,登入失敗次數限制預設是:「失敗5次,1分鐘後才可再次登入。」但如果要求的功能是:「失敗3次,1分鐘後才可登入;再失敗3次,3分鐘後才可登入;再失敗3次,5分鐘後才可登入。」要如何實現?下面將實際示範此登入失敗次數限制的功能。

版本

Laravel 5.5 以上

改寫登入類別設定

app\Http\Controllers\Auth\LoginController.php

<?php

...
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use App\Cache\AdvancedRateLimiter

class LoginController extends Controller
{
    use AuthenticatesUsers;

    ...

    /**
     * Get the rate limiter instance.
     *
     * @return \App\Http\Controllers\Auth\AdvancedRateLimiter
     */
    protected function limiter()
    {
        return app(AdvancedRateLimiter::class);
    }

    /**
     * The maximum number of attempts to allow.
     *
     * @var integer
     */
    protected $maxAttempts = 3;

    /**
     * The number of minutes to throttle for.
     *
     * @var integer|array
     */
    protected $decayMinutes = [1, 3, 5];
}

LoginController 類中,增加自訂方法覆蓋 AuthenticatesUsers 類原本的方法:

  • limiter 方法是返回登入失敗次數限制的類,原本是返回RateLimiter 類(實現登入失敗次數限制的類),但本例要擴充新方法,因此返回了我們下面創建的子類別AdvancedRateLimiter
  • $maxAttempts 屬性是設定登入失敗次數。
  • $decayMinutes 屬性是登入失敗達上限後,須等待的分鐘數。但我們要實現的功能是每次都等待不一樣的時間,因此傳入一個陣列,輸入每次的等待分鐘數。

如果只是要修改 Laravel 原本的錯誤次數設定,新增 $maxAttempts 屬性及 $decayMinutes 屬性並設定值即可完成。

擴充登入失敗次數限制功能

新增類別 AdvancedRateLimiter

app\Cache\AdvancedRateLimiter.php

<?php

namespace App\Cache;

use Illuminate\Cache\RateLimiter;

class AdvancedRateLimiter extends RateLimiter
{
    /**
     * Increment the counter for a given key for a given decay time.
     *
     * @param string $key
     * @param float|int|array $decayMinutes
     * @return int
     */
    public function hit($key, $decayMinutes = 1)
    {
        if (is_array($decayMinutes)) {
            if (! $this->cache->has($key.':timer')) {
                if (! $this->cache->has($key.':step')) {
                    $this->cache->add($key.':step', 0, 1440);
                } else {
                    $this->cache->increment($key.':step');
                }
            }
            $step = $this->cache->get($key.':step', 0);
            $step = $step < count($decayMinutes) ? $step : count($decayMinutes) - 1;
            $decayMinutes = $decayMinutes[$step];
        }

        return parent::hit($key, $decayMinutes);
    }

    /**
     * Clear the hits and lockout timer for the given key.
     *
     * @param string $key
     * @return void
     */
    public function clear($key)
    {
        $this->cache->forget($key.':step');

        parent::clear($key);
    }
}
  • hit 方法是在登入錯誤後,執行登入錯誤次數記錄遞增的方法。為了實現每次登入錯誤等待的時間可以不一樣,我們讓傳入的變數 $decayMinutes 可以接受傳入陣列,第一次登入錯誤等待時間為 陣列[0] 的分鐘數(本例為1分鐘),第二次為 陣列[1] 的分鐘數(例:3分鐘),而第三次為 陣列[2] 的分鐘數(例:5分鐘),之後的登入錯誤等待時間皆為陣列的最後的元素的分鐘數。
  • clear 方法是成功登入後,將時間、次數重設,下一次再登入錯誤後,將從頭開始計數。

此時登入失敗次數限制的功能已改寫完成,再次登入並輸入錯誤的帳號或密碼,重複數次即可看到結果。


尚未有邦友留言

立即登入留言