ログインフォーム表示
ルーティング定義
ルーティングファイルにAuth::routes();
を記述することでユーザー認証関係のルーティングが自動設定される。その中には、以下のログインフォームへのルーティングが含まれる。
- メソッド:GET
- URL:
login
- アクション:
Auth\LoginController@showLoginForm
- ルート名:
login
showLoginFormアクション
LoginController
コントローラーはAuthenticatesUsers
トレイトを利用していて、その中でshowLoginForm
アクションが定義されている。
1 2 3 4 5 6 7 8 9 10 |
..... use Illuminate\Foundation\Auth\AuthenticatesUsers; ..... class LoginController extends Controller { ..... use AuthenticatesUsers; ..... } |
AuthenticatesUsers
トレイトのshowLoginForm()
アクションメソッドは以下の通りで、auth.register
ビューをレンダリングしている。
auth.register
ビューは初期状態では存在しないのでコマンドで生成するかカスタムで作成する必要がある。
1 2 3 4 5 6 7 8 9 |
trait AuthenticatesUsers { ..... public function showLoginForm() { <span class="pl-k">return</span> <span class="pl-en"><span class="pl-token" data-hydro-click="{"event_type":"code_navigation.click_on_symbol","payload":{"action":"click_on_symbol","repository_id":7548986,"ref":"6.x","language":"PHP","originating_url":"https://github.com/laravel/framework/blob/6.x/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php","user_id":null}}" data-hydro-click-hmac="ef26ce1776afd7f9cd106dc44ebf6df058d74ede58cd7afd624f89705e45f651">view</span></span>(<span class="pl-s">'auth.login'</span>); } ..... } |
フォームからのPOSTとログイン実行
ルーティング定義
ルーティングファイルにAuth::routes();
を記述することで、以下のルーティングが定義される。
- メソッド:POST
- URI:
login
- アクション:
Auth\LoginController@login
loginアクション
showLoginForm
アクションと同じく、login
アクションもAuthenticatesUsers
トレイトで定義されている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
trait AuthenticatesUsers { <span class="pl-k">use</span> <span class="pl-v">RedirectsUsers</span>, <span class="pl-v">ThrottlesLogins</span>; ..... public function login(Request $request) { $this->validateLogin($request); // If the class is using the ThrottlesLogins trait, we can automatically throttle // the login attempts for this application. We'll key this by the username and // the IP address of the client making these requests into this application. if (method_exists($this, 'hasTooManyLoginAttempts') && $this->hasTooManyLoginAttempts($request)) { $this->fireLockoutEvent($request); return $this->sendLockoutResponse($request); } if ($this->attemptLogin($request)) { return $this->sendLoginResponse($request); } // If the login attempt was unsuccessful we will increment the number of attempts // to login and redirect the user back to the login form. Of course, when this // user surpasses their maximum number of attempts they will get locked out. $this->incrementLoginAttempts($request); return $this->sendFailedLoginResponse($request); } .... } |
このアクションの動作は以下の通り。
バリデーション
最初はログインフォームのバリデーション。
1 |
$this->validateLogin($request); |
validateLogin()
メソッドは同じAuthenticatesUsers
トレイトで定義されている
1234567protected function validateLogin(Request $request){$request->validate([$this->username() => 'required|string','password' => 'required|string',]);}
連続エラー時の抑止処理
次はログインエラーが連続したときのログイン抑止処理。ここで捕捉されなければ後段のログイン認証に移る。
1 2 3 4 5 6 |
if (method_exists($this, 'hasTooManyLoginAttempts') && $this->hasTooManyLoginAttempts($request)) { $this->fireLockoutEvent($request); return $this->sendLockoutResponse($request); } |
- ここで呼ばれている
hasTooManyLoginAttempts()
、fireLockoutEvent()
、sendLockoutResponse()
の各メソッドは全てThrottlesLogins
トレイトで定義されているhasTooManyLoginAttempts()
はログイントライ回数のがmaxAttempts()
(デフォルトでは5回)を越えているかどうかをチェック
123456protected function hasTooManyLoginAttempts(Request $request){return $this->limiter()->tooManyAttempts($this->throttleKey($request), $this->maxAttempts());}fireLockoutEvent()
はLockout
イベントを発火させる
1234protected function fireLockoutEvent(Request $request){event(new Lockout($request));}sendLockoutResponse()
は一定時間ログインを抑止する
12345678910111213protected function sendLockoutResponse(Request $request){$seconds = $this->limiter()->availableIn($this->throttleKey($request));throw ValidationException::withMessages([$this->username() => [Lang::get('auth.throttle', ['seconds' => $seconds,'minutes' => ceil($seconds / 60),])],])->status(Response::HTTP_TOO_MANY_REQUESTS);}
表示例。秒数は30秒程度で試行ごとに変化した。Too many login attempts. Please try again in 37 seconds.
認証チェック
上記で、バリデーションと連続トライ回数以内の確認が通ったなら、attemptLogin()
で認証チェックを行う。
1 2 3 |
if ($this->attemptLogin($request)) { return $this->sendLoginResponse($request); } |
attemptLogin()
は同じAuthenticatesUsers
トレイトで定義されている。
123456protected function attemptLogin(Request $request){return $this->guard()->attempt($this->credentials($request), $request->filled('remember'));}$this->guard()
はファサード関係の複雑な処理を経て、\Illuminate\Auth\SessionGuard
クラスのインスタンスとなる$this->credentials()
は以下のように定義されていて、ユーザー名とパスワードが認証に使われる
1234protected function credentials(Request $request){return $request->only($this->username(), 'password');}SessionGuard::attempt()
は以下のように認証・ログインを行う
12345678910111213141516171819202122public function attempt(array $credentials = [], $remember = false){$this->fireAttemptEvent($credentials, $remember);$this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);// If an implementation of UserInterface was returned, we'll ask the provider// to validate the user against the given credentials, and if they are in// fact valid we'll log the users into the application and return true.if ($this->hasValidCredentials($user, $credentials)) {$this->login($user, $remember);return true;}// If the authentication attempt fails we will fire an event so that the user// may be notified of any suspicious attempts to access their account from// an unrecognized user. A developer may listen to this event as needed.$this->fireFailedEvent($user, $credentials);return false;}SessionGuard::login()
メソッドでは、セッション更新、Rememberトークン処理、ユーザーのセットなどが行われる
ログイン失敗時のカウント
ログイン失敗時には失敗回数をカウントアップする。この結果は連続エラーのチェックで参照される。
1 2 3 4 5 6 |
// If the login attempt was unsuccessful we will increment the number of attempts // to login and redirect the user back to the login form. Of course, when this // user surpasses their maximum number of attempts they will get locked out. $this->incrementLoginAttempts($request); return $this->sendFailedLoginResponse($request); |