Breeze - iruma-tea/laravel-base-11 GitHub Wiki
Laravelでは認証のスターターキットとして、Laravel Breezeという仕組みが用意されている。
Laravel Breezeは、ユーザー登録、ログイン、ログアウトなどの基本的は認証機能を提供する。
Laravel Breezeをインストールすると、routes/web.phpの内容が上書きされる。
インストールする前に、routes/web.phpの内容をコピーして別、ファイルに保存しておくこと。
- ComposerにLaravel Breezeを追加する
composer require laravel/breeze --dev
- Laravel Breezeをインストール
-
php artisan breeze:install
- 機能確認
- ユーザー登録
-
http://localhost:8000/register
- Name: laravelusr
- Email: [email protected]
- Password: laravelpass
- ConfirmPassword: laravelpass
- 以下、画面キャプチャー
-
http://localhost:8000/register
- ユーザー登録
-
Laravelの認証機能はガードとプロバイダーによって構成される。
- ガード(config/auth.php)
- 認証方法の種類を指定する。
- セッションによる認証やトークンによる認証などが指定できる。
- プロバイダ(config/auth.php)
- ユーザー情報の永続化方法の種類を指定する。
- Eloqumentやクエリビルダなどが指定できる。
リクエストオブジェクトのvalidateメソッドを利用。
valudateに配列でルールを渡す。
パスワードルールにあるRules\Password::defaults()
はデフォルトパスワードルールの
制御をかけます。特に何も設定しない場合は「8文字以上」のルールのみ適用される。
パスワードルールを変更するには、Password::defaults()
を書き換えることで実現する。
パスワードルールには次のようなメソッドが指定できる。
メソッド | 説明 |
---|---|
min($num) | $num以上であること |
letters() | 1文字以上の文字(アルファベット)を含むこと |
mixedCase() | 1文字以上の大文字、小文字を含むこと |
numbers() | 1文字以上の数字を含むこと |
symbols() | 1文字以上の記号を含むこと |
uncompromised() | 漏えい済みのパスワードでないこと |
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
Hash::make($request->password)は入力されたパスワードのハッシュ化を行ったいる。
ハッシュ化とは文字列を不規則で推測不可能な文字列へ変換する処理のことを言う。
パスワードを平文で保持していた場合、何らかの理由でテーブルの情報が流出した際の被害は
計り知れない。パスワードのような重要な情報には不可逆なハッシュ化を行うことで、少しでもリスクを小さくすることをお試みます。
ユーザー登録イベントの発火部分コードは以下の通り。
event(new Registered($user));
Laravelではイベントとリスナの仕組みが用意されている。
どこかのプログラムでイベントクラスを呼び出す(発火させる)と、リスナクラスの処理が実行される仕組みです。
上記の例では、Registered(登録した)というイベントを発火させています。
イベントとリスナの設定はapp/Providers/EventServieProvider.phpでされています。
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
];
Registeredに対して、SendEmailVerificationNotificationリスナが設定されています。
SendEmailVerificationNotificationは名前の通り、確認メールを送るリスナです。
ユーザー情報をセッション情報に保存する
Auth::login($user)
Authクラスは認証の核となるクラスです。Auth::login($user);は$userを認証済みとしてセッションに保管する。
IDとパスワードが一致しているかは確認しない。
loginメソッドはすでに認証済みとして扱うので注意が必要。IDとパスワードを確認する場合、別のメソッド(attempt)を使用する。
attemptメソッドも後ほど紹介しますが、*Authクラスの主なメソッドを一覧に示す。
メソッド | 説明 |
---|---|
Auth::login($user) | $userを認証済みとして保管する |
Auth::attempt(['email' => $email, 'password' => $password]) | $emailと$passwordをデータベースと照合、一致すればtrue、しなければfalseを返す |
Auth::check() | 認証済みの場合はtrue、未認証の場合falseを返す |
Auth::id() | 認証済みの場合、IDを返す |
Auth::user() | 認証済みの場合、ユーザーオブジェクトを返す |
ホーム画面にリダイレクト部分コードは以下の通りです。
return redirect(RouteServiceProvider::HOME);
リダイレクトに設定されているRouteServiceProvider::HOMEはapp/Providers/RouteServiceProvider.phpの次の設定を参照している。
public const HOME = '/dashboard';
認証処理はapp/Http/Controllers/Auth/AuthenticatedSessionController.phpで実装されている。
public function store(LoginRequest $request): RedirectResponse
{
$request->authenticate();
$request->session()->regenerate();
return redirect()->intended(RouteServiceProvider::HOME);
}
storeメソッドはログインボタンをクリックしたときのリクエストを受付ます。
最初に記述されている $request->authenticate(); の処理で認証しています。
$requestは app/Http/Requests/Auth/LoginRequest.phpなので、その中から
authenticateメソッドを探す。
public function authenticate(): void
{
$this->ensureIsNotRateLimited();
if (! Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) {
RateLimiter::hit($this->throttleKey());
throw ValidationException::withMessages([
'email' => trans('auth.failed'),
]);
}
RateLimiter::clear($this->throttleKey());
}
if文の条件の中で、Authクラスのattemptメソッドが呼び出される。
attemptメソッドで認証処理が行われる。
attemptメソッドの第一引数$this->only('email', 'password')はリクエストの中から、emailとpasswordだけを
取り出す。この二つの情報をユーザーテーブルと照会して認証を行う。
第二引数にはリクエストからrememberをbooleanに変換して取り出している。rememberはログイン情報を記録するか否かのチェックボックスです。
trueを渡すとユーザーを無制限、または、ログアウトするまで認証状態を維持するようになる。
routes/web.phpを確認する。
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');
middleware。ミドルウェアとは、リクエストをコントローラーで処理する前後に、別の処理を挟み込む仕組みのこと。
meiddlewareメソッドに 'auth' を指定すると、「ユーザーが未認証だった場合、ログイン画面にリダイレクトする。」
ミドルウェアがコントローラーでの処理の前に挟み込まれる。
ミドルウェアの設定はapp/Http/Kernel.php
に記載がある。
protected $middlewareAliases = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'precognitive' => \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
'auth'に\App\Http\Middleware\Authenticate::classが指定されているのが分かる。
以下、\App\Http\Middleware\Authenticate::classの内容を転記。
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Http\Request;
class Authenticate extends Middleware
{
protected function redirectTo(Request $request): ?string
{
return $request->expectsJson() ? null : route('login');
}
}
ミドルウェアでは、handleメソッドがコントローラーの処理の前に実行されるメソッドですが、
このクラスには handleメソッドが定義されていない。
handleメソッドは親クラスである Illuminate\Auth\Middleware\Authenticateクラスに定義される。
その中で認証の確認をしており、認証がされていない場合はApp\Http\Middleware\AuthenticateのredirectToメソッドが呼び出され、
ログイン画面にリダイレクトする仕組みになっている。
認証処理の実装の前に、ユーザー登録時のメール確認について、
初期設定ではユーザー登録時、メールアドレスの確認メールは送信されない。
送信されるようにするには、Userモデルに「MustVerifyEmail」を実装する。
- 「.env」にメール送信設定
-
Gmailを利用したLaravelのメール送信設定
- Gmailの設定内容
- MAIL_MAILER=smtp
- MAIL_HOST=smtp.gmail.com
- MAIL_PORT=587
- MAIL_USERNAME=[email protected] // gmailのアドレス
- MAIL_PASSWORD=xxxxxxxx // アプリパスワード
- MAIL_ENCRYPTION= // 何も設定しない
- MAIL_FROM_ADDRESS=[email protected] // MAIL_USERNAMEと同じ
- MAIL_FROM_NAME="laravel便り" // メール送信元名
- Gmail送信/受信の確認
- Gmailの設定内容
-
Gmailを利用したLaravelのメール送信設定
- ガードとプロバイダで、認証方式とモデル(テーブル)を指定する。
- authミドルウェアで、認証が必要なリクエストを保護する。
- guestミドルウェアで、認証が不要なリクエストを保護する。
- Authクラスを使用して、ログインなどの認証に関する処理を実装する。
Laravelに最初から用意されているユーザーとは別のユーザー(管理者)を追加し書籍関連の
処理は管理ユーザーのみが閲覧、操作できるようにする。
-
ガードとプロバイダの設定
- 新しく管理ユーザー(Admin)用のガードとプロバイダを用意する。
- 既存のユーザーテーブルとは分けて管理したいため、ガードとプロバイダを追加する。
-
ガードの追加
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
],
-
プロバイダの追加
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
],
],
-
-
モデルの作成とマイグレーション
- 管理ユーザーとしてApp\Models\Adminを参照するように指定しました。指定したモデルがはまだ存在しない為、以下のコマンドで新規に作成する。
-
php artisan make:model Admin -m
- -mオプションはマイグレーションファイルも作成される。
- マイグレーションファイルの編集
- 以下の項目を追加する
$table->string('name');
$table->string('login_id')->unique();
$table->string('password');
- 以下の項目を追加する
- マイグレーションの実行
php artisan migrate
- Adminモデルの変更
- 認証に使用するモデルはAuthenticatable(Illuminate\Foundation\Auth\User)を継承する
- パスワードは$hiddenに設定する。
- 管理者(Admin)のファクトリを作成
- php artisan make:factory Admin
- 管理者(Admin)のシーダーファイルを作成する
- php artisan make:seeder AdminsTableSeeder
- シーダーを実行する
- php artisan db:seed --class=AdminsTableSeeder
-
- 管理ユーザーとしてApp\Models\Adminを参照するように指定しました。指定したモデルがはまだ存在しない為、以下のコマンドで新規に作成する。
-
ビューとコントローラーの作成
- ログイン画面の作成
- resources/auth/adminフォルダにlogin.blade.phpを作成する
- 認証処理を実装する。Laravel Breezeにならって、リクエストオブジェクト内で認証処理を実装する。
php artisan make:request Auth/Admin/LoginRequest
- 管理者ユーザー用のコントローラを作成する
php artisan make:controller Auth/Admin/AuthenticatedSessionController
- ログイン画面の作成
-
ミドルウェアの設定