Lesson 10

認証

Lesson 10 Chapter 1
ログイン画面と新規登録画面の作成

Lesson10では認証に関する処理とその画面の作成を行っていきます。Lesson5ではLaravelの認証機能を使って認証処理を実装しましたが、Lesson10ではそれらの処理を1から作成し、より具体的な流れを確認していきましょう。

ログイン画面の作成

ログイン画面のイメージ

ログイン画面

1. login.blade,phpの作成

ログイン画面用のbladeファイルを作成していきます。ファイル数が増えてきたので、ここで新たにauthフォルダを作成し以下ディレクトリにbladeファイルを作成してください。

resources > views > auth > login.blade.php

login.blade.php
<!doctype html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Laravel_Todo</title>

    <link rel="dns-prefetch" href="//fonts.gstatic.com">
    <link href="https://fonts.bunny.net/css?family=Nunito" rel="stylesheet">
    <link href="{{ asset('/css/style.css') }}" rel="stylesheet">

    @vite(['resources/sass/app.scss', 'resources/js/app.js'])
</head>
<body>
    <div id="app">
        <div class="w-50 m-auto">
            <div class="login_container m-5 p-3 text-center">
                <div>
                    <p class="text-center fs-3 p-3">ログイン</p>
                </div>

                <div class="">
                    <form action="" method="">
                        <div>
                            <input
                              type="text"
                              class="w-50 username"
                              placeholder="メールアドレスを入力"
                            >
                        </div>
                        <div>
                            <input
                              type="text"
                              class="w-50 password"
                              placeholder="パスワードを入力
                            >
                        </div>
                        <div class="w-50 m-auto success_btn_area">
                            <input
                              type="submit"
                              value="ログイン"
                              class="btn btn-primary login_btn"
                            >
                        </div>
                        @csrf
                    </form>
                </div>
                <a href={{ route("register") }}>新規登録はこちら</a>

            </div>
        </div>
    </div>
</body>
</html>

2. LoginControllerの作成

続いてログイン画面の表示を行うControllerとログイン画面を表示する処理としてloginメソッドを準備しましょう。

ターミナル、コマンドプロンプト
php artisan make:controller Auth/LoginController

「Auth/LoginController」のようにスラッシュ(/)で区切ることでAuthフォルダが存在すればその配下に、存在しなければ自動でAuthフォルダが作成され、作成されたAuthフォルダ内にLoginControllerが作成されます。

app > Http > Controllers > Auth > LoginController

LoginController
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class LoginController extends Controller
{
  // ログイン画面の表示
  public function login()
  {
    return view("auth.login");
  }
}

Lesson8で行なったページの表示については各blade.phpをviews配下に作成していましたが、今回はviewsの配下にauthフォルダを作成し、その中にlogin.blade.phpを作成しました。その場合、「return view("フォルダ名.ファイル名")」と参照する必要がありますので覚えておきましょう。

3. ルーティングの設定

作成したlogin.blade.phpとLoginControllerのloginメソッドを紐づけるため、ルーティングの設定を行いましょう。

web.php
Route::get("/login", [App\Http\Controllers\Auth\LoginController::class, "login"])->name("login");

4. cssファイルの修正

認証用のcss追加とTODO一覧画面部分にも一部追加を行います。

style.css
@charset "UTF-8";
/* 認証 */
.email,
.password,
.username {
    border-radius: 5px;
    border: 1px solid silver;
    height: 40px;
    padding: 10px;
    margin-top: 20px;
}

.success_btn_area {
    text-align: right;
    padding: 30px 0;
}

/* TODO一覧画面 */
.task_container,
.completed_container,
.login_container, // こちらも追加
{
    border: 1px solid none;
    border-radius: 5px;
    box-shadow: 0 10px 25px 0 rgba(0, 0, 0, 0.2);
}

// 省略

5. ログイン画面の確認

以上でログイン画面の作成は完了になります。URL(http://127.0.0.1:8000/login)へアクセスし、ログイン画面が表示されるか確認してみてください。

ログイン画面

新規登録画面のイメージ

続いては新規登録画面の作成を行っていきます。流れはログイン画面と同じ為、重複する解説は省略します。

新規登録画面

1. register.blade.phpの作成

resources > views > auth > register.blade.php

register.blade.php
<!doctype html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Laravel_Todo</title>

    <link rel="dns-prefetch" href="//fonts.gstatic.com">
    <link href="https://fonts.bunny.net/css?family=Nunito" rel="stylesheet">
    <link href="{{ asset('/css/style.css') }}" rel="stylesheet">

    @vite(['resources/sass/app.scss', 'resources/js/app.js'])
</head>
<body>
    <div id="app">
        <div class="w-50 m-auto">
            <div class="register_container m-5 p-3 text-center">
                <div>
                    <p class="text-center fs-3 p-3">新規登録</p>
                </div>

                <div class="">
                    <form action="" method="">
                        <!-- ユーザー名入力欄 -->
                        <div>
                            <input
                              type="text"
                              class="w-50 username"
                              placeholder="ユーザー名を入力"
                            >
                        </div>

                        <!-- メールアドレス入力欄 -->
                        <div>
                            <input
                              type="email"
                              class="w-50 email"
                              placeholder="メールアドレスを入力"
                            >
                        </div>

                        <!-- パスワード入力欄 -->
                        <div>
                            <input
                              type="password"
                              class="w-50 password"
                              placeholder="パスワードを入力"
                            >
                        </div>

                        <!-- 確認用パスワード入力欄 -->
                        <div>
                            <input
                              type="password"
                              class="w-50 password"
                              placeholder="確認用パスワードを入力"
                            >
                        </div>
                        <div class="w-50 m-auto success_btn_area">
                            <input
                              type="submit"
                              value="新規登録"
                              class="btn btn-primary"
                            >
                        </div>
                        @csrf
                    </form>
                </div>
                <a href={{ route("login") }}>ログインはこちら</a>

            </div>
        </div>
    </div>
</body>
</html>

2. RegisterControllerの作成

ターミナル、コマンドプロンプト
php artisan make:controller Auth/RegisterController

app > Http > Controllers > Auth > RegisterController

RegisterController
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class RegisterController extends Controller
{
    public function register()
    {
        return view("auth.register");
    }
}

3. ルーティングの設定

web.php
Route::get("/register", [App\Http\Controllers\Auth\RegisterController::class, "register"])->name("register");

4. cssファイルの修正

style.css
@charset "UTF-8";
/* 認証 */
.email,
.password,
.username {
    border-radius: 5px;
    border: 1px solid silver;
    height: 40px;
    padding: 10px;
    margin-top: 20px;
}

.success_btn_area {
    text-align: right;
    padding: 30px 0;
}

/* TODO一覧画面 */
.task_container,
.completed_container,
.login_container,
.register_container // 追加
{
    border: 1px solid none;
    border-radius: 5px;
    box-shadow: 0 10px 25px 0 rgba(0, 0, 0, 0.2);
}

// 省略

5. 新規登録画面の確認

以上でログイン画面の作成は完了になります。URL(http://127.0.0.1:8000/register)へアクセスし、ログイン画面が表示されるか確認してみてください。又、「新規登録はこちら」と「ログインはこちら」でログイン画面と新規登録画面の行き来ができるようにもなっていますので、そちらも合わせて確認しておきましょう。

新規登録画面

Lesson 10 Chapter 2
usersのデータ登録

chapter2ではchapter1で作成した新規登録画面からユーザーの登録を行えるように処理を実装していきます。

新規登録処理の実装

それでは新規登録に合わせて処理の記述と修正を行っていきましょう。

1. register.blade.php

まず初めにregister.blade.phpの記述の修正を行っていきます。

resources > views > auth > register.blade.php

register.blade.php
<form action={{ route("register.store") }} method="post">
<!-- ユーザー名入力欄 -->
<div>
  <input
    type="text"
    class="w-50 username"
    name="username"
    placeholder="ユーザー名を入力"
  >
</div>

<!-- メールアドレス入力欄 -->
<div>
  <input
    type="email"
    class="w-50 email"
    name="email"
    placeholder="メールアドレスを入力"
  >
</div>

<!-- パスワード入力欄 -->
<div>
  <input
    type="password"
    class="w-50 password"
    name="password"
    placeholder="パスワードを入力"
  >
</div>

<!-- 確認用パスワード入力欄 -->
<div>
  <input
    type="password"
    class="w-50 password"
    name="password_confirmation"
    placeholder="確認用パスワードを入力"
  >
</div>

<!-- 新規登録ボタン -->
<div class="w-50 m-auto success_btn_area">
  <input
    type="submit"
    value="新規登録"
    class="btn btn-primary"
  >
</div>
@csrf
</form>

修正箇所の解説を行っていきいます。

<form action={{ route("register.store") }} method="post">

こちらは新規登録ボタンを押した際に実行する登録処理のルーティングになります。ルーティングについては後ほど設定していきます。

各inputタグのname属性

各入力欄に入力したデータをcontrollerで受け取りが行えるようにname属性の設定を行っています。命名については任意ですが、関連する命名にすると良いです。

以上がregister.blade.phpの変更点です。

2. RegisterControllerに登録用のメソッドの作成

これまではページの表示処理のみ行なってきましたが、実際に入力内容をデータベースへ登録する処理を実装します。RegisterControllerへメソッドの追加を行いましょう。

app > Http > Controllers > Auth > RegisterController

RegisterController
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
// 追加
use App\Models\User;

class RegisterController extends Controller
{
    public function register()
    {
        return view("auth.register");
    }

    // ユーザーの登録処理
    public function storeUser(Request $request)
    {
        User::create([
            "name" => $request->username,
            "email" => $request->email,
            "password" => $request->password
        ]);

        return redirect()->route("auth.login");
    }
}

以下が解説になります。

Request $request

Laravelでは送られてきたデータを受け取る際にRequestクラスを使用します。入力されたユーザーの名前、メールアドレス、パスワードのデータ全てがstoreUserメソッドの引数に指定している$requestとしてデータの受け取りを行うことが可能です。又、$requestから特定のデータのみを受け取りたい場合は「$request->name属性(inputタグに指定)」とすることで名前、メールアドレス、パスワードなど単一の値を取得することができます。

User::create

データ操作(データの作成)を行う為、Userモデルを使用します。モデルクラスのcreateメソッドを使用することでデータの作成を行うことが可能です。この際、連想配列の形式で記述を行なってあげましょう。連想配列は「カラム名 => データ」とする必要があります。

return redirect()->route("auth.login")

これまでは指定のページを表示する為、ルーティングでgetメソッドを使用して、「return view」としていましたが、データベースの操作においてはpostメソッドなどを使用します。postメソッドの場合は「return redirect」と遷移先の指定を行い、route("auth.login")でログイン画面表示を行なっているルーティングのnameメソッドを指定しています。

3. パスワードの暗号化

Lesson5の項目でハッシュ化について説明しました。ユーザーのパスワードは非常に重要な項目となる為、セキュリティの面でハッシュ化は必須だと考えておきましょう。上記のControllerの記述ではパスワードのハッシュ化がまだ済んでいない為、ハッシュ化を行います。

変更前

RegisterController
"password" => $request->password;

変更後

RegisterController
use Illuminate\Support\Facades\Hash;

// 省略

"password" => Hash::make($request->password);

Hashファサードを使うことでハッシュ化することができます。Hashファサードを使用する際はuse宣言する必要がありますので、上記の記述も忘れずに行ってください。実際にハッシュ化を行う前と後のデータも確認しておきます。

[ハッシュ化前]
入力欄に入力した内容がそのまま表示されます。

デバッグ
"test"

[ハッシュ化後]
入力欄に入力した内容をランダムな英数字に置き換わり、データとして扱われます。

デバッグ
"$2y$10$o.fu8LkOhbBCaQKKaQMN5O6WuWyx2oiWaQsCf6UvClx3s05HENucq"

以上がパスワードの暗号化(ハッシュ化)です。主にパスワードに使用されますが、ハッキングを防ぐ為にも大切なデータはこのように暗号化をし、扱っていく方法があることも覚えておきましょう。

4. ルーティングの設定

続いて追加した処理を実行する為、ルーティングの設定を行っていきます。

routes > web.php

web.php
<?php


Route::get("/register", [App\Http\Controllers\Auth\RegisterController::class, "register"])->name("register");

// 追加
Route::post("/register/store", [App\Http\Controllers\Auth\RegisterController::class, "storeUser"])->name("register.store");

新規登録画面表示のルーティングに続いて追記しましょう。これまでのルーティングはページの表示を行うことが目的とした処理だった為、getメソッドを使用していましたが、新規登録のようにデータの登録を行う処理の場合はpostメソッドでルーティングを定義する必要があります。指定するメソッドが違うだけで、他の記述についてはこれまでと同様になります。

登録処理はこれで以上となります。この先の項目で実際に動作確認を行っていきます。

Lesson 10 Chapter 3
usersのデータ認証

chapter2でusersのデータ登録処理を行いました。続いてchapter3ではユーザーのデータ認証について実装していきましょう。

ユーザー認証処理の実装

ユーザーのデータ認証とはログイン機能のことです。登録されているデータと入力された内容が一致していればログインを行い、不一致であればログインを行わない処理になります。

1. login.blade.php

login.blade.phpの記述の修正を行っていきます。

resources > views > auth > login.blade.php

login.blade.php

<!-- エラーメッセージ -->
@if(session("error_message"))
<span class="text-danger">{{ session("error_message") }}
@endif

<form action={{ route("login.check") }} method="post">
<div>
    <input
      type="text"
      class="w-50 email"
      name="email"
      placeholder="メールアドレスを入力"
    >
</div>
<div>
    <input
      type="password"
      class="w-50 password"
      name="password"
      placeholder="パスワードを入力"
    >
</div>
<div class="w-50 m-auto success_btn_area">
    <input
      type="submit"
      value="ログイン"
      class="btn btn-primary login_btn"
    >
</div>
@csrf
</form>

修正箇所の解説を行っていきいます。

@if(session("error_message"))

認証失敗時のエラーメッセージをcontrollerの処理でsessionに格納し、ifディレクティブを使用して該当するsessionがあればメッセージの表示を行っている部分になります。

<form action={{ route("login.check") }} method="post">

ログインボタンを押した際に実行する認証処理のルーティングになります。ルーティングについては後ほど設定していきます。

各inputタグのname属性

各入力欄に入力したデータをcontrollerで受け取りが行えるようにname属性の設定を行っています。命名については任意ですが、関連する命名にすると良いです。

以上がlogin.blade.phpの変更点です。

2. LoginControllerに認証用のメソッドの作成

入力された内容と登録されているデータを照合する処理、つまりログインの処理を実装します。LoginControllerへメソッドの追加を行いましょう。

Http > Controllers > Auth > LoginController>

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\User;

// 追加
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{
    // 省略

    // ユーザーのログイン処理
    public function loginCheck(Request $request)
    {
        $email = $request->email;
        $password = $request->password;

        if (!Auth::attempt(["email" => $email, "password" => $password])) {
            session()->flash("error_message", "メールアドレス、又はパスワードの入力に誤りがあります。");
            return redirect()->route("login");
        }

        return redirect()->route("todo.lists");
    }
}

以下が解説になります。

if (!Auth::attempt(["email" => $email, "password" => $password]))

Laravelでは認証用のメソッドとしてattemptメソッドが用意されています。Authクラスは認証に関するクラスで認証処理の実装や認証済みのユーザー情報などを簡単に出力することが可能です。「Auth::attempt(["カラム名" => データ])」の形式にすることで入力された内容と登録されているデータの照合ができます。一致していればtrue、不一致であればfalseとなり、今回の場合は!Authとしているため、不一致であればログイン画面へリダイレクトする処理、一致していれば作成したtop.blade.phpへリダイレクトする処理を実装しています。

session()->flash(...)

こちらは入力に誤りがあった場合にblade.phpで表示するメッセージをsessionに格納しています。if文が処理される場合はデータの照合が取れなかったことになる為、sessionにエラーメッセージを持たせ、そのメッセージを出力します。

login.blade.php

<!-- エラーメッセージ -->
@if(session("error_message"))
<span class="text-danger">{{ session("error_message") }}
@endif

ifディレクティブを使用し、controllerで記述したsession("error_message")が存在すれば第二引数に指定したメッセージが出力される仕組みとなっています。ログイン画面で適当な入力をした際の画面イメージがこちらになります。

ログインエラー

バリデーションで実装しない理由

認証機能については、バリデーションで実装はせず一致しているか不一致かだけを判定しブラウザへエラーメッセージの出力を行います。例えば「メールアドレスが間違っています」、「パスワードが間違っています」などと具体的なメッセージの出力をしてしまうことによって、ハッキングのリスクも高くなる為です。このようなリスクも考慮する必要がある為、注意しながら実装していきましょう。

3. ルーティングの設定

認証の処理を実行する為、ルーティングの設定を行っていきます。

routes > web.php

web.php
<?php


Route::get("/login", [App\Http\Controllers\Auth\LoginController::class, "login"])->name("login");

// 追加
Route::post("/login/check", [App\Http\Controllers\Auth\LoginController::class, "loginCheck"])->name("login.check");

認証もデータを送る処理になる為、getではなくpostメソッドを使用します。

以上で認証(ログイン)処理の実装は完了になります。こちらもバリデーションを実装する必要があるので、実装後に動作確認を行っていきましょう。

Lesson 10 Chapter 4
バリデーションを実装する

chapter3では新規登録時のバリデーションの準備をしていきます。バリデーションを実装することでユーザーにとっても使いやすく、セキュリティ面でも安全なサービスを構築することが可能になります。

バリデーションとは

入力された内容がルールを満たしているかをチェックする機能になります。例えば新規登録でパスワードと確認用パスワードの入力内容が不一致だった場合、「パスワードが一致しません」など出るメッセージを目にしたことがあるかもしれませんが、それがバリデーションです。

新規登録用のバリデーション実装準備

Lesson4ではバリデーションについてvalidatorメソッド、validateファサード、FormRequestの3パターンご紹介しました。今回はその中でもFormRequestを使用したバリデーションの実装を行っていきます。理由としてはクラスとして別ファイルにバリデーションを定義しておくことにより、controllerのコードがスマートになることでその他の修正や機能実装の影響を受けづらい点や、チーム開発を想定した場合には見やすいコードを心がける必要がある為です。FormRequestでの実装はこのようなメリットが存在し、実践でも使われる機会が多いのでFormRequestでのバリデーション実装を学習していきましょう。

1. 新規登録用のFormRequestの作成

FormRequestはコマンドで作成することができますので、以下を実行しましょう。

ターミナル、コマンドプロンプト
php artisan make:request RegisterRequest

RegisterRequestの部分には作成したいファイル名を「○◯Request」の形で指定してあげます。作成されたRegisterRequestを確認してみましょう。

app > Http > Requests > RegisterRequest.php

RegisterRequest
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class RegisterRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return false;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, mixed>
     */
    public function rules()
    {
        return [
            //
        ];
    }
}

新規登録の内容に合わせてバリデーションの設定を行っていきます。

authorize()

authorizeメソッドではデフォルトでfalseが指定されています。こちらはFormRequestのOn/Offのスイッチのような役割をしています。FormRequestを適用させたい場合はtrueにする必要がある為、返り値にtrueを指定しましょう。

RegisterRequest
public function authorize()
    {
        return true;
    }

rules()

rulesメソッドにはバリデーションのルールを設定していきます。以下は設定をし終えた状態です。

RegisterRequest
public function rules()
{
  return [
    "username" => "required | string | min:2",
    "email" => "required | email | unique:users",
    "password" => "required | min:4 | max:8 | confirmed",
    "password_confirmation" => "required",
  ];
}

書き方としては連想配列の形式で、「"カラム名" => "ルール1|ルール2|ルール3"」となります。複数ルールを設ける場合はパイプライン(|)を使用して区切ってあげましょう。バリデーションルールについてはLesson4で紹介したルールのみで構成していますので、ここでは省略致します。

messages()

messagesメソッドにはバリデーションの発生時に出力するバリデーションメッセージを設定していきます。デフォルトではmessagesメソッドは存在しないため、自身で用意しましょう。

RegisterRequest
public function rules()
{
  // 省略
}

public function messages()
{
  return [
    "required" => "必須項目です。",
    "username.min" => "名前は2文字以上で入力してください。",
    "email.unique" => "既に登録されているメールアドレスです。",
    "password.min" => "パスワードは4文字以上で入力してください。",
    "password.max" => "パスワードは8文字以内で入力してください。",
    "password.confirmed" => "確認用パスワードと一致していません。"
  ];
}

バリデーションメッセージの定義は、「"バリデーションルール" => "バリデーションメッセージ"」とします。例えばユーザー名とパスワードのように同じバリデーションルールを設定していて名前は2文字、パスワードは4文字としてバリデーションメッセージを変更したい場合は「"バリデーションルール.カラム名" => "バリデーションメッセージ"」としてあげることで項目ごとにメッセージの変更をすることが可能です。

2. ControllerでFormRequestの呼び出し

FormRequestの準備が完了したので、続いてはバリデーションを実行するcontrollerのメソッドでFormRequestを呼び出していきましょう。以下修正してください。

RegisterController
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\User;

// 追加
use App\Http\Requests\RegisterRequest;

class RegisterController extends Controller
{
    public function register()
    {
        return view("auth.register");
    }

    // ユーザーの登録処理
    public function storeUser(RegisterRequest $request)// 修正
    {
        User::create([
            "name" => $request->username,
            "email" => $request->email,
            "password" => $request->password
        ]);

        return redirect()->route("auth.login");
    }
}

controllerへの記述はバリデーションを実装したいメソッドの第一引数にRegisterRequestを代入します。又、RegisterRequestクラスを使用するのでuse宣言をしてあげることで実装が可能となります。

バリデーションメッセージの表示

バリデーションメッセージを表示するため、register.blade.phpを修正します。

resources > views > auth > register.blade.php

register.blade.php
<form action={{ route("register.store") }} method="post">
<!-- ユーザー名入力欄 -->
<div>
  <input
    type="text"
    class="w-50 username"
    name="username"
    placeholder="ユーザー名を入力"
  >
</div>
<!-- ユーザー名のバリデーションメッセージ -->
@if($errors->first("username"))
<span class="text-danger">{{ $errors->first("username") }}</span>
@endif

<!-- メールアドレス入力欄 -->
<div>
  <input
    type="email"
    class="w-50 email"
    name="email"
    placeholder="メールアドレスを入力"
  >
</div>
<!-- メールアドレスのバリデーションメッセージ -->
@if($errors->first("email"))
<span class="text-danger">{{ $errors->first("email") }}</span>
@endif

<!-- パスワード入力欄 -->
<div>
  <input
    type="password"
    class="w-50 password"
    name="password"
    placeholder="パスワードを入力"
  >
</div>
<!-- パスワードのバリデーションメッセージ -->
@if($errors->first("email"))
<span class="text-danger">{{ $errors->first("password") }}</span>
@endif

<!-- 確認用パスワード入力欄 -->
<div>
  <input
    type="password"
    class="w-50 password"
    name="password_confirmation"
    placeholder="確認用パスワードを入力"
  >
</div>

<!-- 新規登録ボタン -->
<div class="w-50 m-auto success_btn_area">
  <input
    type="submit"
    value="新規登録"
    class="btn btn-primary"
  >
</div>
@csrf
</form>

バリデーションが発生した際にはRegisterRequestのmessagesメソッドで定義しているバリデーションメッセージが$errorsへ代入されます。ifディレクティブを使用し、バリデーションが発生している場合にはバリデーションメッセージを表示する処理を追記しました。

以上でバリデーションの実装は完了です。

Lesson 10 Chapter 5
ログアウトの実装

一通りの機能が完成しました。最後に認証後はログアウトの機能が必要になるのでログアウト機能の実装とそれに伴いルーティングのグループ設定を行いましょう。

1. ログアウトボタンの設置

ログアウトボタンはログイン後のページに表示させる為、top.blade.phpへボタンの設置を行います。

resources > views > top.blade.php

top.blade.php

// 省略
<body>
    <div id="app">
        // 1行追加
        <div class="w-75 m-auto text-end">
          <a href={{ route("logout") }}>ログアウト</a>
        </div>
        <div class="w-75 m-auto">
            <div class="task_container m-5 p-3">

// 省略

ログアウトボタンの設置はこれで完了です。

2. ログアウト処理の実装

LoginControllerへログアウト処理用のlogoutメソッドを作成していきます。

app > Http > Controllers > Auth > LoginController

top.blade.php
// 省略

public function logout()
{
  Auth::logout();

  return redirect()->route("login");
}

ログアウトの機能はAuthクラスにあるlogoutメソッドを1行実行するだけでログアウトの機能を実装することができます。ログアウト後はログインページへリダイレクトされるよう設定しましょう。

3. ルーティングの設定

ログアウトボタンを押下時にlogoutメソッドが実行されるようルーティングの設定を行います。ログアウトではページの表示は行いませんが、Request等を使用して何かデータを送受信が起きる処理ではない為、getメソッドで設定します。

web.php
// 省略

Route::post("/register/store", [App\Http\Controllers\Auth\RegisterController::class, "storeUser"])->name("register.store");

// 追加
Route::get("/logout", [App\Http\Controllers\Auth\LoginController::class, "logout"])->name("logout");

Route::get("/top", [App\Http\Controllers\TodosController::class, "TodoLists"])->name("todo.lists");

// 省略

以上でログアウト機能の実装は完了になります。

4. ルーティングのグループ設定

認証機能とログアウト機能の実装により、認証、又は非認証のユーザーなのかを区別することができました。そこでルーティングには認証済みのユーザーのみが実行できるルーティングのグループ分けを行っていきます。例えばこのグループ設定が行われていない場合、ログインしていないユーザーがログイン後のページにアクセスできてしまうといった不具合が生じます。このような不具合を防ぐためにルーティングのグループ分けは必須となります。

グループ設定方法

ルーティングのグループ設定は以下のようにgroupメソッドを使用して行います。ログインしていないユーザーにのみ実行を許したい操作をguest内でルーティングを行い、ログインしているユーザーにのみ実行を許したい操作はauth内でルーティングを行います。

web.php
// 認証前
Route::group(["middleware" => "guest"], function () {
    // ルーティング
});

// 認証後
Route::group(["middleware" => "auth"], function () {
    // ルーティング
});

下記がグループ設定を行った後のルーティングになります。ログイン画面や新規登録画面の表示、処理はログインしていないユーザーのみ実行可能。TODO一覧画面やTODO作成画面、TODO編集画面、ログアウト処理はログイン済みのユーザーのみ実行可能な処理とグループ分けを行いました。

web.php
// 認証前
Route::group(["middleware" => "guest"], function () {
    // ログイン画面の表示
    Route::get("/login", [App\Http\Controllers\Auth\LoginController::class, "login"])->name("login");
    // ログインの処理
    Route::post("/login/check", [App\Http\Controllers\Auth\LoginController::class, "loginCheck"])->name("login.check");
    // 新規登録画面の表示
    Route::get("/register", [App\Http\Controllers\Auth\RegisterController::class, "register"])->name("register");
    // 新規登録の処理
    Route::post("/register/store", [App\Http\Controllers\Auth\RegisterController::class, "storeUser"])->name("register.store");
});

// 認証後
Route::group(["middleware" => "auth"], function () {
    // ログアウトの処理
    Route::get("/logout", [App\Http\Controllers\Auth\LoginController::class, "logout"])->name("logout");
    // TODO一覧画面の表示
    Route::get("/top", [App\Http\Controllers\TodosController::class, "TodoLists"])->name("todo.lists");
    // TODO作成画面の表示
    Route::get("/create", [App\Http\Controllers\TodosController::class, "TodoCreate"])->name("todo.create");
    // TODO編集画面の表示
    Route::get("/edit", [App\Http\Controllers\TodosController::class, "TodoEdit"])->name("todo.edit");
});

以上でルーティングのグループ設定は完了となります。このグループ分けを行ったことで実際にどのような動きになるのか、chapter6の動作確認で確認していきます。

Lesson 10 Chapter 6
新規登録と認証の動作確認

userの登録から認証までの機能が完成しました。最後にそれぞれの動作の確認を行ってきます。

userのデータ登録動作確認

1. データの作成

まずはuserの登録処理を実行してみます。各入力欄を埋め登録を行いましょう、成功すればログイン画面へ遷移します。

ユーザー作成 ログイン画面

2. データベースの確認

phpMyAdminで入力した通りのユーザーが作成されているかデータを確認してみましょう。又、この時パスワードのハッシュ化が行われているかの確認もしておきます。

ユーザー作成後のデータベース

3. バリデーションの確認

各入力欄でバリデーションの動作確認を行い、バリデーションメッセージが表示されるか確認しましょう。

ユーザー作成のバリデーション

以上がuserの登録動作確認になります。

userのデータ認証動作確認

1. データの認証

先ほど登録を行ったuserのメールアドレスとパスワードを入力し、ログインボタンを押下してみましょう。認証が成功すればtopページであるtop.blade.phpへ遷移します。

ユーザー認証 Todoトップページ

2. データの認証失敗時

登録されているデータと入力した内容に相違があればページの遷移が行われず、sessionメッセージが表示されることを確認しておきましょう。

ログインエラー

以上がuserのデータ認証動作確認になります。

ルーティンググループ分けの動作確認

ルーティングでグループ分けを行ったことによりどのような動きになるのかを確認していきます。ログイン画面にいる状態でURL(http://127.0.0.1:8000/top)へアクセスしてみましょう。認証されていないユーザーがアクセスすると現在のページURL(http://127.0.0.1:8000/login)へリダイレクトが行われます。

ログイン画面

続いてログインを行い、TODO一覧画面にいる状態で認証前のページ(http://127.0.0.1:8000/login)へアクセスしてみましょう。

Todoトップページ 404ページ

認証済みのユーザーが未認証のルーティングを実行したことにより/homeへリダイレクトされました。このように認証済みユーザーが未認証のルーティングを実行すると/homeへリダイレクトするようデフォルトの設定がLaravelでは行われています。今回の場合は/homeではなくTODO一覧画面へリダイレクトされるよう設定の変更を行いましょう。

app > Providers > RouteServiceProvider.php

変更前

RouteServiceProvider.php
public const HOME = '/home';

変更後

RouteServiceProvider.php
public const HOME = '/top';

以上で設定の変更は完了になります。TODO一覧画面(http://127.0.0.1:8000/top)にいる状態でログイン画面(http://127.0.0.1:8000/login)に移動してみるとTODO一覧画面へのリダイレクト処理が実行されます。

Todoトップページ

ユーザーの作成から認証までの動作確認はこれで以上になります。