前回のユーザー登録では、登録後は自動的に認証され、ユーザーはあたかもすでにログインしたような状態となります。

しかし、デフォルトの設定の2時間のアイドルを過ぎると、ログアウトされてしまいます。そうなると必要なのはユーザー認証のためのログイン画面です。

ログイン画面に必要なのは、

app/Http/Controllers/AuthController.php

のコントローラ。前回にはこのコントローラは、登録画面に使われましたが、コントローラ中の以下のトレイトの使用により、

use AuthenticatesAndRegistersUsers

さらに、

そのトレイトの定義で使われているトレイト、

use AuthenticatesUsers

により、ログインが機能します。その定義を見てみましょう。以下のコードは説明のために、ログインスロットルなどの部分を省いています。


namespace Illuminate\Foundation\Auth;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Lang;

trait AuthenticatesUsers
{
    use RedirectsUsers;

    // ログイン画面の表示
    public function getLogin()
    {
        // app/resources/views/auth/authenticate.blade.phpがあるならそれを使用
        if (view()->exists('auth.authenticate')) {
            return view('auth.authenticate'); 
        }

        // authenticate.blade.phpがないなら、login.blade.phpを使用
        return view('auth.login');
    }

  // ログインボタンを押したら以下を実行
    public function postLogin(Request $request)
    {
        // 入力バリデーション
        $this->validate($request, [
            $this->loginUsername() => 'required', 'password' => 'required',
        ]);

        $credentials = $this->getCredentials($request);

        if (Auth::attempt($credentials, $request->has('remember'))) {
       // 認証成功後の処理:リダイレクトとか
            return $this->handleUserWasAuthenticated($request);
        }

    // 認証失敗なら、ログイン画面にエラーを表示
        return redirect($this->loginPath())
            ->withInput($request->only($this->loginUsername(), 'remember'))
            ->withErrors([
                $this->loginUsername() => $this->getFailedLoginMessage(),
            ]);
    }

    // 認証成功後の処理。目的の画面にリダイレクト
    protected function handleUserWasAuthenticated(Request $request)
    {
        if (method_exists($this, 'authenticated')) {
            return $this->authenticated($request, Auth::user());
        }
        return redirect()->intended($this->redirectPath());
    }

  // ユーザーのクレデンシャル、つまりemailとpasswordをゲット
    protected function getCredentials(Request $request)
    {
        return $request->only($this->loginUsername(), 'password');
    }
    
    // ログアウト、つまりクッキーの削除。そしてリダイレクト。デフォルトはルートディレクトリへ
    public function getLogout()
    {
        Auth::logout();
        return redirect(property_exists($this, 'redirectAfterLogout') ? $this->redirectAfterLogout : '/');
    }
    
  ...

postLogin()では、入力バリデーションの後に、Auth::attemptが実行されます。そこでは、config/auth.phpで指定したドライバー(Eloquent)を使用して、DBにEメールと暗号化されたパスワードがマッチするかどうかチェックして結果を返します。マッチしたなら、そこでセッションを作成して認証された事実を残します。認証関連のイベントでフックされているコードもそこで実行されます。

その後に実行される、handleUserWasAuthenticated()では、redirect()->intended()により、アクセスを試みた初期のURLへリダイレクトします。

例えば、認証以前に、

http://localhost/demo-auth/public/password/edit

へアクセスを試みると、まず認証のためにログイン画面へリダイレクトされて、ログイン成功後には、上のURLへ自動的に移動します。デフォルトでは、$this->redirectPath()へ移行します。

ログアウトは、ログインのようにボタンとかは必要とせずに、現在ログインしているならログアウトのURLにアクセスするだけで、ログインのセッションを無効とします。get Login()Auth::logout()がその処理を行います。

上記のコントローラで使用されるテンプレート、login.blade.phpには、以下のようなフォームが含まれます。

<form method="POST" action="/auth/login">
    {!! csrf_field() !!}

    <div>
        Eメール
        <input type="email" name="email" value="{{ old('email') }}">
    </div>

    <div>
        パスワード
        <input type="password" name="password" id="password">
    </div>

    <div>
        <input type="checkbox" name="remember"> 次回から入力を省略
    </div>

    <div>
        <button type="submit">ログイン</button>
    </div>
</form>

さて、これでログイン画面は動作しますが、このフォームで使用される「次回から入力を省略」のチェックボックスは何でしょう?

ここがオフでは、ログインのセッションは2時間で時間切れとなり、再度ログインが必要となります。ここをオンとしてログインが成功となると現在の設定では5年間は、ログインなしで認証が必要な画面へのアクセスが可能となります。Laravelではセキュリティを上げるために、ここがオンのときはトークンを作成してDBに保存し、クッキーの値とマッチするかのチェックを行っています。

さて、ユーザーの認証の部分ができたところで、次回は、どうやってLaravelがこの認証の情報をもとにプライベート画面を保護するかを見てみましょう。

By khino