0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Laravelで認可設計をちゃんとやってみた(Gate vs Policyの使い分け)

0
Posted at

Laravelには認可機能として

  • Gate
  • Policy

が用意されています。

ただ正直なところ、

  • とりあえず if ($user->role === 'admin')
  • Bladeで @if 書いて制御

みたいな実装をしてしまいがちです。

今回は、実務で認可設計を整理したときの考え方をまとめます。


よくあるアンチパターン

① Controllerに直接role判定を書く

if ($user->role !== 'admin') {
    abort(403);
}

② Bladeでroleを直接見る

@if(auth()->user()->role === 'admin')
    <button>削除</button>
@endif

一見シンプルですが、

  • ロジックが散らばる
  • 変更に弱い
  • テストしづらい
  • 権限変更時に全探索が必要

という問題があります。


Laravelの正しい選択肢

Laravelでは認可を

  • Gate(行為ベース)
  • Policy(モデルベース)

に分けて設計できます。


GateとPolicyの違い

Gate

特定の行為に対する認可

例:

  • 管理画面に入れるか
  • レポートをエクスポートできるか
  • 特定の操作を実行できるか

→ モデルに紐づかない


Policy

特定のモデルに対する操作の認可

例:

  • このPostを編集できるか
  • このUserを削除できるか
  • このOrderを更新できるか

→ モデルが存在する


使い分けの基準

状況 使うべきもの
モデルに対するCRUD Policy
単なる行為の許可 Gate
画面表示制御 @can
実行時のチェック authorize()

実装例

① Gateの定義

App\Providers\AuthServiceProvider.php

use Illuminate\Support\Facades\Gate;

public function boot()
{
    Gate::define('access-admin-panel', function ($user) {
        return $user->role === 'admin';
    });
}

Controllerで使用

public function index()
{
    $this->authorize('access-admin-panel');

    return view('admin.index');
}

Bladeで使用

@can('access-admin-panel')
    <a href="/admin">管理画面</a>
@endcan

Policyの実装例

① Policy作成

php artisan make:policy PostPolicy --model=Post

② Policy定義

public function update(User $user, Post $post)
{
    return $user->id === $post->user_id;
}

③ Controllerで使用

public function update(Post $post)
{
    $this->authorize('update', $post);

    // 更新処理
}

④ Bladeで使用

@can('update', $post)
    <button>編集</button>
@endcan

なぜ@ifではなく@canを使うのか?

@if(auth()->user()->role === 'admin') と書くと

  • ロール変更時に全修正が必要
  • 将来的な権限拡張に弱い
  • 意図が分かりづらい

一方 @can なら、

「何ができるか」という抽象的な表現になる

設計が行為ベースになるのがポイントです。


設計を整理して気づいたこと

認可設計で重要なのは

ユーザーが何者かではなく、何ができるか

roleはあくまで内部実装。

ControllerやBladeには
「行為」だけを書きます。


まとめ

Laravelで認可を整理するなら:

  • モデルに対する操作 → Policy
  • モデルに紐づかない行為 → Gate
  • 表示制御は @can
  • 実行時は authorize() を必ず通す
  • roleを直接見ない

これだけで設計がかなりスッキリします。

最初は少し手間に感じますが、

ロジックが一箇所に集約され、
後からの変更にも強い構成になります。

Laravelの認可は強力なので、
「なんとなくif」から卒業するだけで
コードの質はかなり上がります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?