やりたいこと
apiのrouteに対して適宜認可を掛ける。対象になるのは、usersテーブル。これはLaravelのデフォルトのユーザーテーブル。
show/editできるのは、管理者とその当該ユーザーのみとか。
やったこと
<?php Route::middleware('auth')->group(function () { Route::resources([ 'user' => 'UserController',
として、(このauthはログイン状態を見ているだけ)
app/Http/Controllers/UserController.php にリソースコントローラの認可を設定
<?php class UserController extends Controller { /** * UserController constructor. */ public function __construct() { $this->authorizeResource(User::class, 'user'); }
で、ポリシーファイル app/Policies/UserPolicy.php
<?php class UserPolicy { use HandlesAuthorization; /** * Determine whether the user can view the model. * * @param \App\User $user * @param \App\User $model * @return mixed */ public function view(User $user, User $model) { return $this->viewAny($user) || $user->id === $model->id; }
を作ってサービスプロバイダーに登録 app/Providers/AuthServiceProvider.php
<?php class AuthServiceProvider extends ServiceProvider { /** * The policy mappings for the application. * * @var array */ protected $policies = [ App\User::class => App\Policies\UserPolicy::class,
症状
403エラーが返ってくる
{ exception: "Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException", file: "/home/vagrant/myapp/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php" line: 223 message: "This action is unauthorized." } trace : {...} }
みたいな。
対処方法
ControllerのメソッドDIを変えると全然違う
<?php public function show($id)
の場合だと、403になる。というか、そもそもPolicyのview()まで来ていない。
<?php public function show($id)
の場合だと、403になる。というか、そもそもUserPolicy::view()まで来ていない。
<?php public function show(Request $request, User $user)
とすると、Policy::view()まで来るようになる。
ということで
Policyを使って認可する場合は、Controllerのメソッド引数も考慮しなければならないようだ。
LaravelってDIの魔法みたいなことするけど、こういうわけわからない挙動もあるのどうなんだ…