「基礎から学ぶLaravel」の感想・備忘録3

スポンサーリンク

認可

認可とは

  • 認可とは「ユーザーが権限を持っているかどうか判定すること」である。
  • Laravelでは認可を実現する仕組みとしてポリシーとゲートがある。

ポリシーとゲート

  • ポリシー=モデル単位でポリシークラスを作成してアクセス制限を定義する
  • ゲート=Authサービスプロバイダにモデルに依存しないアクセス制限を定義する
  • ポリシーとゲートの大きな違いは、権限判定時にモデルを渡すかどうかである。
    ちょっとした判定をしたいだけであれはゲートを使えばいいが、数が増えてくると管理が難しくなる。
    モデルに関する権限判定はポリシーで行い、モデルの必要がない権限判定はゲートで行うのがよいと著者は書いているが正解はない。

ポリシー

sail artisan make:policy BookPolicy

  • Laravel 5.8以降では、ポリシー名を「モデル名+Policy」とするとサービスプロバイダへのポリシー登録が不要になる
  • –model=BookのようにするとviewAnyなど7つのメソッドが定義された形で作成される
    (後述のauthorizeResourceを使う場合に便利)
public function update(Admin $admin, Book $book): bool
{
  // ログインユーザーとbooksテーブルのadmin_idを比較
  return $admin->id === $book->admin_id;
}
// createやstoreメソッドではモデルインスタンスがないので引数は1つのみ
public function create(Admin $admin): bool
{
  return substr($admin->login, 0, 4) === 'hoge';
}

コントローラーでポリシーを適用する場合

authorizeメソッドを使うと、権限がない場合に403が返される。

public function view(Book $book): View
{
  $this->authorize('view', $book); // 第1引数=ポリシーのメソッド名、第2引数=モデルインスタンス
  return view('book.view', ['book' => $book]);
}
public function create(): View
{
  $this->authorize('create', Book::class); // モデルインスタンスがないの第2引数はクラス::classを渡す
  // 以下省略
}

コントローラーでポリシーを適用する場合(authorizeResourceメソッド)

アクションメソッドごとに$this->authorize()を書くのが面倒な場合、コントローラのコンストラクタに$this->authorizeResource(Book::class, 'book');のように追加すると、以下のポリシー制限が適用される。
(第2引数はルートで定義したリクエストパラメータ) https://qiita.com/avocadoneko/items/658961b68a348a3cb3fd
ただし、authorizeResource()の場合はポリシーにメソッド定義がない場合は403となるので注意。

ルートにcanミドルウェアを追加してポリシーを適用する場合

Route::get('admin/books/create')->can('create', App\Models\Book::class);

テンプレートで適用する場合

@canまたは@cannnotディレクティブを使う。

@can('view', $book)
<li><a href="{{route('book.view', $book->id)}}">{{$book->title}}:{{$book->price}}円</a></li>
@else
<li>{{$book->title}}:{{$book->price}}円</li>
@endcan

ゲート

ゲートはapp/Providers/AuthServiceProvider.phpに定義する。

public function boot(): void
{
  Gate::define('hoge-user', function (Admin $admin) {
    return substr($admin->login_id, 0, 4) === 'hoge';
  });
}

適応方法はポリシーと同じ(モデルを渡さないだけ)

コメント