やりたいこと
Laravel でログイン時に試行回数を設定したい
デフォルトだと同一IPからの制限になっているようでなっていません
ググって参考記事とか真似して作っても
特定のIPから、入力した認証情報(emailとか、ユーザ名とか)が複数回、同じものの場合、
IPと入力した認証情報での組み合わせでロックになります。
なので、別の認証情報を入力すれば再度認証処理が走ります
下記はlaravelのデフォルトのログインです(1分で5回でロック)
— 棗(なつめ) (@natsume_aurlia) October 14, 2020
例えば、1分間に2回ミスるとロックの場合
1.) emailにhoge@hoge.com
2.) emailにhoge@hoge.com
←二回同じなのでロック
3.) emailにfuga@fuga.com
←異なる認証情報なのでチェックが普通に走る
これじゃなんの意味もない...総当りし放題では...
原因
大雑把にロックの流れは、
1.キャッシュでカウントしたもので制限超えているか確認
2.認証情報でログインできる試行
3.失敗したらキャッシュでカウント
LoginControllerで使ってるtrait
のAuthenticatesUsers
のlogin
メソッドの中で行っています
publicfunctionlogin(Request$request){$this->validateLogin($request);// ここで制限超えているか確認しているif(method_exists($this,'hasTooManyLoginAttempts')&&$this->hasTooManyLoginAttempts($request)){$this->fireLockoutEvent($request);return$this->sendLockoutResponse($request);}if($this->attemptLogin($request)){return$this->sendLoginResponse($request);}// これでキャッシュでカウントしてる!!!!$this->incrementLoginAttempts($request);//これ!return$this->sendFailedLoginResponse($request);}
incrementLoginAttempts
でカウントしています
んでこの中身です
protectedfunctionincrementLoginAttempts(Request$request){$this->limiter()->hit($this->throttleKey($request),$this->decayMinutes()*60);}
んで、このhit
メソッドでキャッシュに入れたり、時間をどうのこうのしてますがここはいいのですが
第一引数として渡している$this->throttleKey($request)
でキャッシュのキーを設定しているのですがこいつが問題です
/**
* Get the throttle key for the given request.
*
* @param \Illuminate\Http\Request $request
* @return string
*/protectedfunctionthrottleKey(Request$request){returnStr::lower($request->input($this->username())).'|'.$request->ip();}
$request->input($this->username()
はメールアドレスだったり、パスワードと何を入力させるのか設定しているやつ(ここではメールアドレスとして進めます)
なので、メールアドレスとipを文字列でつないでキーを作っています....
なので当然メールアドレスの入力が変わればもう一度認証の試行を行います
解決策
throttleKey
をオーバーライドして、ipだけ返すようにします
protectedfunctionthrottleKey(Request$request){return$request->ip();}
あとは時間と試行回数をいい感じにしておけば
入力値に関わらずIPで制限になります
protected$maxAttempts=10;protected$decayMinutes=5;