基礎から学ぶ Laravel
posted with ヨメレバ
株式会社クロノス 佐野大樹 シーアンドアール研究所 2023年06月13日
認可
認可とは
- 認可とは「ユーザーが権限を持っているかどうか判定すること」である。
- 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';
});
}
適応方法はポリシーと同じ(モデルを渡さないだけ)