Laravelの【Policy】機能を使って、本人と管理者以外、プロフィールを更新できなくする方法を解説します。
しっかりとアクセス制限をかけておかないと、不正なアクセスによってユーザーのプロフィールを書き替えられてしまう可能性があります。
Policyの設定方法をステップごとに解説していきますね。
Laravelで本人と管理者以外はプロフィールを更新できなくする方法
今回は、各ユーザーのプロフィール編集ページへの更新に制限をかけていきます。
プロフィール編集ページは、Userテーブルと連携しています。
Laravelでは色々な方法で制限をかけられますが、今回はPolicyを使っていきます。
Policyは、特定のモデルと結び付けて、制限をかけられる方法。
Laravelのマニュアルには次のように書かれています。
ポリシーは特定のモデルやリソースに関する認可ロジックを系統立てるクラスです。
*引用元:Laravel8 認可
今回はUserモデルと結び付けていきたいので、ピッタリの機能です。
具体的な手順を5ステップに分けて解説していきますね。
- Policyファイルを作成する
- Policyファイルを編集する
- AuthServiceProviderに登録する
- コントローラーに制限をかける
- 管理者も編集可能にする
Policyファイルを作成する
まずは下記のコマンドでPolicyファイルを作成します。
コマンドの最後に、結びつけるモデル名をいれておきます。
1 |
php artisan make:policy UserPolicy --model=User |
名前の付け方は、【モデル名+Policy】としておきましょう。
今回はUserモデルに連携させるので、UserPolicyとします。
コマンドを実行すると、app/policiesの中に、ポリシーファイルが作成されます。
モデル名をつけてPolicyファイルを作ると、最初から7つのメソッドが入っています。
Policyファイルを編集する
app/policiesの中にUserPolicy.phpファイルができているので、開きます。
一番上に、use宣言を加えておきます。
1 |
use App\Models\User; |
public function updateに、下記のように書いておきましょう。
1 2 3 4 5 6 7 8 |
public function update(User $user, User $model) { if($user->id == $model->id){ return true; } else { return false; } } |
ちょっとわかりにくいのですが、updateの後には、引数が二つ入っています。
最初の引数【User $user】が、今ログインしているユーザー、2つ目の引数【User $model】は、プロフィールに掲載されたユーザーです。
両者が同一人物であれば、trueを返します。
AuthServiceProviderに登録する
作成したPolicyは、AuthServiceProviderに登録します。
app/ProvidersからAuthServiceProvider.phpファイルを開き、下記のように登録しておきましょう。
1 2 3 |
protected $policies = [ App\Models\User::class=>App\Policies\UserPolicy::class, ]; |
コントローラーに制限をかける
これで準備OKです。
プロフィールを編集する部分のコントローラーに、今作ったUserPolicyを適用させます。
1 2 3 4 5 |
public function edit(User $user){ $this->authorize('update', $user); return view('profile.edit', compact('user')); } |
一度テストしてみましょう
これで一度、テストしてみましょう。
次のようにプロフィール編集ページのルートを設定しているとします。
1 |
Route::get('/profile/edit/{user}', 'ProfileController@edit'); |
User部分にログインユーザー以外のIDをいれ、プロフィールページを開こうとしてみます。
403 THIS ACTION IS UNAUTHORIZEDと表示されたら成功。
Policyをリソースコントローラーと効率的に連携させる方法
ここで、ちょっと豆知識。
コントローラーに、メソッドごとに $this->authorize('メソッド', $user);と入れていくのは面倒です。
実はリソースコントローラーを使う場合、最初にコンストラクタを入れてしまう手があります。
そのあとはコントローラーにPolicyに関する記述を入れずにすみます。
詳しい方法はこちらの記事で解説しているので、ご興味があれば、併せてご覧ください。
トラップもあるので、ご注意ください。
そのあたりも、解説しています。
管理者も編集可能にする
最後に管理者もプロフィールを編集できるようにします。
これは、【管理者】権限をどのように設定しているかによって、書き方が変わってきます。
今回はRole(役割)モデルを作り、Userモデルと多対多のリレーションをはってあると想定します。
Roleモデルを作り、リレーションを設定する方法はこちらで解説しています。
Userモデルファイルに、次のような関数を加えます。
1 2 3 4 5 6 7 8 |
public function userHasRole($role_name){ foreach($this->roles as $role){ if($role_name==$role->name){ return true; } return false; } } |
UserPolicyファイルの先ほど作成したupdateメソッドを、次のように書き替えます。
1 2 3 4 5 6 7 8 |
public function update(User $user, User $model) { if($user->id == $model->id || $user->userHasRole('admin')){ return true; } else { return false; } } |
これで「ユーザー本人、あるいは管理者権限があるものなら、TRUEを返す」とできました。
再度テストしてみてください。
さいごに
今回は、ユーザープロフィール編集に制限をかける方法を解説しました。
制限がないWebアプリは、不正な操作がいくらでもできてしまいます。
Policyなどを使って、しっかりアクセス制御をしておきましょう。
制限がしっかりしたWebアプリを作れれば、顧客の信頼も得られます。
関連記事に他の方法もあるので、併せて参考にしてくださいね。