この記事にはプロモーションが含まれています。

【Laravel11】Gate(ゲート)とPolicy(ポリシー)で「認可」機能を実装する

【Laravel11】Gate(ゲート)とPolicy(ポリシー)で「認可」機能を実装する

Webアプリでは、特定の機能を実行する権限があるかどうかをチェックするために「認可」という仕組みを利用します。

また、PHPのフレームワークであるLaravelでは、この「認可」を簡単に実装する仕組みとしてGate(ゲート)とPolicy(ポリシー)が用意されています。

この記事では、Laravel11

Gate(ゲート)とPolicy(ポリシー)を利用して
「認可」機能を実装する方法

を解説していきます。

ケケンタ

「認可」と類似したものに「認証」があります。
この2つの違いについても解説しますので、ぜひ参考にしていただけるとうれしいです!

この記事で分かること
  • Gate(ゲート)とPolicy(ポリシー)を使用して「認可」機能を実装する方法
  • 「認証」と「認可」の違い
  • 「認可」機能のレスポンスをカスタマイズする方法


Amazon Audible(オーディブル)キャンペーンバナー


ケケンタ

ケケンタのITブログでは、WebアプリPHPLaravel)やWeb制作WordPressコーディング)について情報を発信しています。
学習中の方や実務をされている方など多くの方にアクセスいただいていますので、ぜひほかの記事も参考にしてみてください!





目次

「認証」と「認可」の違い

まずは「認証」と「認可」の違いについて解説します。

認証認可
ユーザーの身元を確認すること特定のリソース(機能)へのアクセス権限があるかどうかを確認すること
「認証」と「認可」の違い

混同されがちですが、「認証」と「認可」には、このように役割に明確な違いがあります。

  • 「認証」は、ユーザーの身元を確認して不正アクセスを防ぐための仕組み
  • 「認可」は、「認証」によって身元確認が行われたユーザーに、特定の機能の利用権限があるかどうかをチェックする仕組み

「認可」については、管理者と閲覧者をイメージしていただくと理解しやすいかと思います。

管理者はあらゆる機能を実行する権限を持ちますが、閲覧者にはデータを見る権限しか無く、編集・削除といった機能は実行できません。

ケケンタ

当記事でご紹介するGate(ゲート)やPolicy(ポリシー)は、「認可」を実装するための仕組みです!

ちなみに、Laravelでは「認証」機能を簡単に実装する方法として、Laravel Breezeなどの仕組み(パッケージ)が用意されています。

こちらも今後、別の記事で詳しくお伝えできればと考えています。

なお、もうひとつ「認可」と混同しやすい仕組みとしてバリデーションがあります。
そちらについては以下の記事で実装方法を解説していますので、ご興味のある方はこちらをご覧ください。

Gate(ゲート)とPolicy(ポリシー)の関係性

Laravelで「認可」を実装するには、Gate(ゲート)やPolicy(ポリシー)を利用します。

この2つは、いわばルーティングとコントローラと同じ関係性を持ちます。
公式ドキュメントでもそのような説明があります。

具体的には、以下のように関係性が類似しています。

Gate(ゲート)とPolicy(ポリシー)の関係性
  • ルーティング → Policy(ポリシー)には「認可」の判定用のメソッドを定義
  • コントローラ → Gate(ゲート)にはPolicy(ポリシー)で定義したメソッドを呼び出すときの「名前」を定義
ケケンタ

上記のイメージを持っていただくと、「認可」を実装するハードルもぐっと下がるので参考にしていただければと思います!

【手順】Gate(ゲート)とPolicy(ポリシー)の基本的な使い方

本章では具体的にゲートとポリシーを使用して「認可」を実装する手順を解説します。

前述したように、「認可」はそのユーザーに機能の使用権限があるかどうかをチェックする仕組みです。

したがって、「認可」を実装する際には、前提としてユーザー認証機能が実装されている必要があります。
当記事でもすでにユーザー認証機能が実装されている想定で解説を進めていきます。

なお、当記事では「TODOアプリのタスク編集権限」を例に解説を進めていきます。

ケケンタ

それでは、各STEPを順番に見ていきましょう!

STEP1 Gate(ゲート)を定義する

Gate(ゲート)はApp/Providers/AppServiceProvider.phpboot()メソッドに定義します。

use Illuminate\Support\Facades\Gate;

public function boot(): void
{
    Gate::define('task-edit', [TaskPolicy::class, 'edit']);
}

このソースコードでは、STEP2で、Policy(ポリシー)で実装するedit()メソッドの呼び出し名としてtask-editを定義しています。

STEP2 Policy(ポリシー)に「認可」の判断基準となる処理を記述する

Policy(ポリシー)ファイルはコマンドで作成することが可能です。

具体的には、以下のコマンドで作成します。

php artisan make:policy TaskPolicy

上記のコマンドによりapp/Policiesディレクトリ直下にTaskPolicy.phpが生成されます。

TaskPolicyが生成される
TaskPolicyが生成される

補足として、ポリシーメソッドのサンプルを含んだクラスを生成したい場合は、下記のように--modelオプションを付けます。

php artisan make:policy TaskPolicy --model=Task

続いて、生成されたTaskPolicy.phpに以下のソースコードを記述します。

public function edit(User $user, Task $task)
{
    return $user->id === $task->user_id;
}

上記はGate(ゲート)で認可処理を行う際に使用するメソッドです。

現在ログイン中のユーザID編集対象のタスクのユーザID=タスク作成者が一致するかどうかを検証し、結果をreturnしています。

メソッド名はなんでも大丈夫ですが、ここでは分かりやすくedit(タスク編集ページを表示するコントローラメソッド名と同じ)にしています。

STEP3 「認可」を実行したい箇所にGate(ゲート)による処理を記述する

最後に、STEP1~STEP2で定義した「認可」機能によって権限チェックを行いたい箇所にGate(ゲート)による判定処理を記述します。

/**
 * タスク編集ページを表示
 */
public function edit(Task $task)
{
    // ゲートの基本的な記述
    if (! Gate::allows('task-edit', $task)) {
        abort(403);
    }

    // ~ 認可されたあとの処理 ~

}

上記のedit()は、タスク編集ページを呼び出すためのメソッドです。

実際にタスク編集ページを呼び出す前に、Gate(ゲート)によって権限チェックを行っています。

Gate::allows(‘task-edit’, $task)の「task-edit」はApp/Providers/AppServiceProvider.phpboot()メソッドで定義した、Policy(ポリシー)メソッド呼び出し用の名前です。

また、abort()メソッドに403を渡すことで、権限がないときには403エラーが返るようになります。

403エラー画面
403エラー画面

■ 補足:404を渡せば404エラーが返るようになります。

【補足】Gate(ゲート)の処理を簡単に書く

以上がGate(ゲート)の基本的な書き方ですが、もう少しシンプルに書く方法もあります。

/**
 * タスク編集ページを表示
 */
public function edit(Task $task)
{
    // ゲートの基本的な記述
    // if (! Gate::allows('task-edit', $task)) {
    //     abort(403);
    // }

    // ゲート記述簡単化
    Gate::authorize('task-edit', $task);

    // ~ 認可されたあとの処理 ~

}

上記のようにGate::authorize('task-edit', $task);とするだけで認可処理を実行できます。

エラーメッセージのカスタマイズ

この書き方の場合、エラーメッセージ部分は以下のようになります。

Gate::authorize()によるエラー画面
Gate::authorize()によるエラー画面

もしもエラーメッセージをカスタマイズしたい場合は、Policy(ポリシー)のメソッド内の処理を以下のように修正します。

エラーメッセージをカスタマイズ

use Illuminate\Auth\Access\Response;  // 追加

public function edit(User $user, Task $task)
{
    // 元々の処理
    //return $user->id === $task->user_id;
    
    // エラーメッセージカスタマイズ
    return $user->id === $task->user_id
             ? Response::allow()
             : Response::deny('タスクの編集権限がありません。');
}
エラーメッセージカスタマイズ後の画面
エラーメッセージカスタマイズ後の画面

HTTPレスポンスを任意のものにする

403エラーではなく、別のHTTPレスポンスを返したい場合は以下のように記述することも可能です。

HTTPレスポンスを任意のものにする

use Illuminate\Auth\Access\Response;  // 追加

public function edit(User $user, Task $task)
{
    // 元々の処理
    //return $user->id === $task->user_id;
    
    // エラーメッセージカスタマイズ
    return $user->id === $task->user_id
             ? Response::allow()
             : Response::denyWithStatus(404);
}
HTTPレスポンスを404エラーへ変更
HTTPレスポンスを404エラーへ変更

Gate(ゲート)によるレスポンスのカスタマイズについては他にも色々な仕組みが用意されています。

詳しくはLaravel11 公式ドキュメント(日本語)をご覧ください。

まとめ

以上がLaravel11で「認可」機能を実装する方法でした。

この記事でご紹介したのはGate(ゲート)やPolicy(ポリシー)の使い方の中でも最も基本的な内容です。

ただ、ここまでの内容を理解できていれば、あとは公式ドキュメントをご覧いただくことでご自身の状況に適したカスタマイズができるかと思います。

ケケンタ

この記事が少しでもお役に立ったなら何よりです!

当ブログではLaravelやPHP、WordPressなどに関する情報を発信しています。

ご興味のある方はほかの記事もご覧いただけるとうれしいです。

それでは、最後までご覧いただきありがとうございました!

【Laravel11】Gate(ゲート)とPolicy(ポリシー)で「認可」機能を実装するのアイキャッチ画像

この記事が気に入ったら
フォローしてね!

この記事が良いと思ったらシェアしてね!

コメント

コメントする

CAPTCHA


目次