Laravelでログイン機能を用意しても、それだけでは利用者ごとの操作範囲まで制御できません。
安全なWebアプリケーションには、利用者を確かめる認証と、許可する操作を決める認可の両方が必要です。
この記事では、認証済みの利用者だけに画面を開く方法と、投稿を編集できる利用者をGateで判定する方法を、フォームのアクセシビリティとあわせて説明します。
この記事で学べること
- 認証と認可の役割を区別する考え方
authミドルウェアでルートを保護する方法- Gateで投稿の編集権限を判定する方法
- ラベル、必須表示、エラー通知を備えたフォームの基本
認証と認可の違い
認証は、アクセスしている利用者が誰かを確認する仕組みです。
認可は、確認できた利用者にどの操作を許すかを判定する仕組みです。
| 仕組み | 答える問い | 例 |
|---|---|---|
| 認証 | 誰が利用しているか | ログイン、ログアウト、パスワード再設定 |
| 認可 | 何をしてよいか | 自分の投稿だけを編集する、管理画面を管理者だけに見せる |
たとえば、ログイン済みであることは「すべての投稿を編集してよい」ことを意味しません。
認証で利用者を特定したあと、対象データと操作ごとに認可を判定します。
作業前にLaravelのバージョンを確認する
Laravelの導入手順とファイル構成は、利用するバージョンとスターターキットによって変わります。
旧版向けのBreeze導入手順をそのまま実行せず、作業対象に合うLaravel公式のスターターキット情報を確認してください。
新規プロジェクトの作成例は次のとおりです。
composer global require laravel/installer
laravel new myapp
cd myapp
npm install && npm run build
composer run dev
プロジェクト作成時に選ぶ構成によって認証画面の実装場所が異なるため、この記事では特定の画面ファイルに依存しない認証と認可の基礎を扱います。
バージョン選定や運用まで含めて検討する場合は、PHPとLaravelで業務Webアプリを作る前に決めることも参考になります。
authミドルウェアで認証済みの利用者だけに開く
ミドルウェアは、リクエストが処理へ届く前に条件を確認する仕組みです。
Laravelのauthミドルウェアをルートへ付けると、認証済みの利用者だけがそのルートへ進めます。
use Illuminate\Support\Facades\Route;
Route::middleware('auth')->group(function () {
Route::get('/dashboard', function () {
return view('dashboard');
});
});
この例では/dashboardを保護できますが、投稿の所有者までは判定していません。
authは入口の確認に使い、個別の操作権限はGateまたはPolicyで判定します。
Gateで投稿の編集権限を判定する
Gateは、利用者が特定の操作を実行できるかを真偽値で表す認可ルールです。
次の例では、ログイン中の利用者IDと投稿の作成者IDが一致するときだけ、更新を許可します。
use App\Models\Post;
use App\Models\User;
use Illuminate\Support\Facades\Gate;
public function boot(): void
{
Gate::define('update-post', function (User $user, Post $post): bool {
return $user->id === $post->user_id;
});
}
GateはApp\Providers\AppServiceProviderのbootメソッドで定義できます。
コントローラーでは、更新処理の前に同じルールを呼び出します。
use App\Models\Post;
use Illuminate\Support\Facades\Gate;
public function edit(Post $post)
{
Gate::authorize('update-post', $post);
return view('posts.edit', compact('post'));
}
権限がない場合は処理を先へ進めず、Laravelが認可エラーをHTTP 403レスポンスへ変換します。
Gateの定義方法と判定方法は、Laravel公式の認可ドキュメントで確認できます。
GateとPolicyの使い分け
認可ルールが増えたら、対象とルールのまとまりを見て配置を決めます。
| 方法 | 向いている場面 |
|---|---|
| Gate | 管理画面の閲覧など、単発の操作を小さなルールとして表したいとき |
| Policy | 投稿の閲覧、更新、削除など、一つのモデルに関する複数のルールをまとめたいとき |
最初はGateで認可の流れを理解し、投稿に関する判定が増えた段階でPolicyへ整理すると役割を追いやすくなります。
ログインフォームを理解しやすくする
ログインフォームでは、入力欄の目的、必須かどうか、エラーの内容を見た目とプログラムの両方から把握できるようにします。
<label for='email'>メールアドレス(必須)</label>
<input
id='email'
type='email'
name='email'
value='{{ old('email') }}'
required
@error('email') aria-invalid='true' aria-describedby='email-error' @enderror
>
@error('email')
<p id='email-error' role='alert'>{{ $message }}</p>
@enderror
labelのforと入力欄のidを一致させる- 記号だけに頼らず、ラベル内の「必須」と
required属性で必須項目を示す - エラーがあるときは
aria-describedbyで入力欄とメッセージを結び付ける - ボタンには用途に応じて
type='submit'またはtype='button'を明示する - Tabキーでラベル、入力欄、ボタンへ自然な順序で移動できるか確認する
フォーム部品を共通化するときは、ラベルやエラー関連付けを呼び出し側が欠落させない設計にします。
再利用設計はLaravelのBladeコンポーネントによるUI部品設計、操作確認はキーボード操作とフォーカス表示の実務で詳しく確認できます。
フォームのラベルとエラー通知の考え方は、W3C WAIのフォームチュートリアルにも整理されています。
実装後に確認する順序
- 対象プロジェクトのLaravelバージョンとスターターキットを確認する
- ログイン、ログアウトなど必要な認証ルートを確認する
- 認証が必要なルートへ
authミドルウェアを付ける - 対象データと操作ごとにGateまたはPolicyを定義する
- 未認証、認証済み、所有者、所有者以外の各状態をテストする
- フォームをキーボードと支援技術で確認する
初心者が見落としやすい点
- ログインできることと、対象データを操作できることを同じ扱いにしない
- 編集ボタンを画面から隠すだけで済ませず、サーバー側の更新処理でも認可する
- 必須項目を色や記号だけで伝えない
- 古い解説のコマンドやファイル配置を、バージョン確認なしで転用しない
認証と認可を分けて設計する
Laravelの認証は利用者を特定し、認可はその利用者に許す操作を判定します。
authミドルウェアで入口を守り、GateまたはPolicyで対象ごとの操作を制御し、フォームでは入力方法とエラーを明確に伝えることが実装の基本です。
最初に「誰が、どのデータへ、どの操作をできるか」を表にしてからコードへ落とすと、認可ルールの漏れを見つけやすくなります。
この記事に関連する株式会社greedenの取り組み
認証と認可を正しく分けても、業務ルールを画面と権限設計へ落とし込めなければ、安全で使いやすいサービスにはなりません。株式会社greedenは、要件整理から実装、テスト、保守改善まで一貫したWebシステム開発を支援します。
