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

Warning
這篇文章的內容已經過時了,請使用 Laravel Backoff Limiter 來代替。
Laravel 本身已實現了登入失敗次數限制的功能。在使用 Laravel 的登入驗證時,登入失敗次數限制預設是:
- 失敗5次,
1分鐘後
才可再次登入 - 之後都是每隔
1分鐘
就可以再試5次
但這樣的設定太單純且不安全,如果要增加安全性,要實現的功能是:
- 失敗3次,
1分鐘後
才可登入 - 再失敗3次,
3分鐘後
才可登入 - 再失敗3次,
5分鐘後
才可登入 - …
本文將示範此進階版登入失敗次數限制的功能。
版本
Laravel 5.8 以上
改寫登入類別設定
<?php
...use Illuminate\Foundation\Auth\AuthenticatesUsers;use Illuminate\Http\Request;use App\Cache\AdvancedRateLimiter;
class LoginController extends Controller{ use AuthenticatesUsers;
...
/** * The maximum number of attempts to allow. * * @var int */ protected $maxAttempts = 3;
/** * The number of minutes to throttle for. * * @var int|float|int[]|float[] */ protected $decayMinutes = [1, 3, 5];
/** * Get the rate limiter instance. * * @return \App\Cache\AdvancedRateLimiter */ protected function limiter() { return app(AdvancedRateLimiter::class); }
/** * Increment the login attempts for the user. * * @param \Illuminate\Http\Request $request * @return void */ protected function incrementLoginAttempts(Request $request) { $this->limiter()->hit( $this->throttleKey($request), array_map(function ($decayMinute) { return (int) ($decayMinute * 60); }, (array) $this->decayMinutes()) ); }}
在 LoginController
類中,增加自訂方法覆蓋 AuthenticatesUsers
類原本的方法:
limiter
方法是返回登入失敗次數限制的類,原本是返回RateLimiter
類(實現登入失敗次數限制的類),但本例要擴充新方法,因此返回了我們下面創建的子類別AdvancedRateLimiter
。$maxAttempts
屬性是設定登入失敗次數。$decayMinutes
屬性是登入失敗達上限後,須等待的分鐘數。但我們要實現的功能是每次都等待不一樣的時間,因此傳入一個陣列,輸入每次的等待分鐘數。
如果只是要修改 Laravel 原本的錯誤次數設定,新增 $maxAttempts
屬性及 $decayMinutes
屬性並設定值即可完成。
擴充登入失敗次數限制功能
新增類別 AdvancedRateLimiter
:
<?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 int|int[] $decaySeconds * @return int */ public function hit($key, $decaySeconds = 60) { if (is_array($decaySeconds)) { if (! $this->cache->has($key.':timer')) { if (! $this->cache->has($key.':step')) { $this->cache->add($key.':step', 0, 86400); } else { $this->cache->increment($key.':step'); } }
$step = $this->cache->get($key.':step', 0); $step = $step < count($decaySeconds) ? $step : count($decaySeconds) - 1; $decaySeconds = $decaySeconds[$step]; }
return parent::hit($key, $decaySeconds); }
/** * 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
方法是成功登入後,將時間、次數重設,下一次再登入錯誤後,將從頭開始計數。
此時登入失敗次數限制的功能已改寫完成,再次登入並輸入錯誤的帳號或密碼,重複數次即可看到結果。
- 作者:Lucas Yang
- 文章連結:https://star-note-lucas.me/posts/laravel-login-limiter
- 版權聲明:本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明出處。