Laravel5 で権限管理が必要なシステムを開発しています。権限管理・ロール管理(認可)については、公式ドキュメント(英語(本家)・日本語)に目を通しても実装イメージがわきにくいかと思います。ウェブ上にも参考情報があまりないようなので備忘として残してみました。
やりたいこと
URLベースのアクセス権限管理をしたい。つまり特定のURLにアクセスできるのを(管理者)権限を持ったユーザーに限定、権限のないユーザーがアクセスした場合には403エラー画面を表示という仕様の実現です。
権限管理(認可)の前提として認証(ログイン処理)がありますが、認証には Laravel5 標準の Auth を利用します(以下 Auth による認証が大前提)。
メンテナンス性を重視
シンプルでメンテナンスしやすい実装を心がける。コントローラーのアクションごとにアクセス権限のチェック処理を入れる、といった実装は煩雑な実装はNG。
動作検証したバージョン
Laravel 5.3 での動作を確認していますが、おそらく5.1以降(正確には5.1.11以降)でも動作するかと思います。ただし Laravel はマイナーバージョンで機能やファイル構造が変わるので、バージョンにより多少の読み替えは必要になるかと思います。
さて、前置きが長くなりましたが本題です。
Laravel5 でURLベースの権限管理をする方法
結論から言うと、たった2つのファイルを編集するだけで、Laravel5 ではURLベースの権限管理を実装できます。
1. ゲートを定義
まずはゲートを定義します(ゲートとは何かについては公式ドキュメントの認可を参照のこと)。
ゲートは App\Providers\AuthServiceProvider クラスの boot メソッドで定義します。 Laravel5.3 の場合、ファイルのパスは app/Providers/AuthServiceProvider.php です。
たとえばIDが1,2,3のユーザーが管理者権限を持つケースでは下記のようにゲートを定義します。「管理者グループ」ということでゲート名を’admin’としてみましたが、任意の名前をつけられるので ‘administrator’ とか ‘webmaster’ とかわかりやすければなんでもOKです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/** * Register any authentication / authorization services. * * @return void */ public function boot() { $this->registerPolicies(); // 'admin'ゲートを定義 // ユーザーIDが 1 / 2 / 3 のユーザーを管理者とする Gate::define('admin', function ($user) { return ($user->id == 1 || $user->id == 2 || $user->id == 3); }); } |
簡単のためユーザーIDを管理者グループの判別基準にしていますが、users テーブルに role カラム や グループID をもたせて柔軟に管理しても良いでしょう。
突然 $user という変数が出てきますが、これはログイン時のユーザー情報がセットされる暗黙のインスタンスです。
Gateファサードを使用し、定義します。ゲートは常に最初の引数にユーザインスタンスを受け取ります。関連するEloquentモデルのような、追加の引数をオプションとして受け取ることもできます。
認可 5.3 Laravelより引用
2. ルーティングとミドルウェアの設定
ゲートを定義したら、ルーティングファイルを編集します。Laravel 5.3 の場合 app/routes/web.php になります( 5.1 と 5.2 の場合 app/Http/routes.php )。
middleware がポイントで、auth に加えて can を使います。 具体的にはミドルウェアに can:ゲート名 を指定するだけで、アクセス権限を限定することができます(5.3で確認)。
1 2 3 4 |
// ログイン状態の'admin'ユーザーのみアクセス可能 Route::group(['middleware' => ['auth', 'can:admin']], function () { Route::get('/ban_user', 'BanController@user'); }); |
上記のようにすると、 http://localhost/ban_user にアクセスできるのが、ログインした状態の’admin’ゲートで定義したユーザーだけに限定できます。adminゲートに属していないユーザーがアクセスすると、ミドルウェアにより403ステータスコードのHTTPレスポンスが生成されます。
このように Laravel5 ではコントローラのソースコードを汚すこともなく、URLベースの権限管理(アクセス制限)を簡単に実装できてしまいます。
おまけ – ビューでのロール管理も簡単
URLベースのアクセス制限だけでなく、ビュー上の表示切り替えも簡単です。
Laravel5 標準テンプレートの Blade を使用している場合、ページ中で特定のユーザー(グループ)だけに見せたいコンテンツがある場合は @can(ゲート名) … @endcan で囲むだけです!
1. ゲートを定義のように’admin’というゲートを定義した場合、下記のようになります。
1 2 3 4 5 6 7 |
<ul> <li><a href="/">トップページ</a></li> <li><a href="/post/">投稿一覧</a></li> @can('admin') <li><a href="/ban_user">Banユーザーリスト</a></li> @endcan </ul> |
なおゲートのみ見せたくない場合は cannot(ゲート名) … @endcannot もあります。
まとめ
Laravel5 でURLベースの権限管理をする方法のまとめです。
1. ゲートを定義
2. ミドルウェア auth と can を使ってルーティング設定
3. ビュー・レベルは@can @cannot ディレクティブで制御