current userのroleカラムがadministoratorの時だけ実行できるapiを作りたい
- ミドルウェアを独自に作る(簡単)
- 作成したミドルウェアを通るようにapi.phpを編集する
これにより実現可能。
ジャンプできる目次
やりたいこと
「御託はいいから」って人は飛ばして。
「自分のやりたいこととこの記事は一致してるかまだわからん」って人は読んで。
//api.php(編集前)
Route::get('/hoge', [HogeController::class, 'index']);//管理者だけにしか触らせたくないAPI
ドメイン/api/hoge
を呼び出した際に、ログインしているユーザーが管理者じゃなかったらブロックしたい。
//api.php(ログインしているなら誰でも実行できる書き方)
Route::middleware('auth:sanctum')->group(function(){
Route::get('/hoge', [HogeController::class, 'index']);//管理者だけにしか触らせたくないAPI;
});
単純にログインしているかどうかの判断であればsanctum認証のミドルウェアで挟むだけでいいが、「ログインしているユーザーのroleがadministratorなら」という条件の指定方法は?
ログインしてたらOK!のようにするだけでよければ、下記の記事で解説済み。
Laravel|認証システムsanctumでapiにガードをかけるときの書き方
(今回の記事はsanctum限定の話ではないので割愛)
roleカラムがadministratorであるユーザーでログインしているときだけ、特定のAPIの実行を許可したい。
ユーザーの情報を取得してapi.php内にf文を書きたいところだが、api.php内では多分それができない。
やり方
新たにカーネルを作る
<?php
//プロジェクトディレクトリ/app/Http/Middleware/RoleAuthenticate.php
namespace App\\Http\\Middleware;
use App\\Providers\\RouteServiceProvider;
use Closure;
use Illuminate\\Http\\Request;
use Illuminate\\Support\\Facades\\Auth;
class RoleAuthenticate
{
/**
* Handle an incoming request.
*
* @param \\Illuminate\\Http\\Request $request
* @param \\Closure $next
* @param string|null ...$guards
* @return mixed
*/
public function handle(Request $request, Closure $next, ...$guards)
{
if (Auth::guard()->check()) {
if(Auth::user()->role == 'administrator'){
//return response()->json(['status'=>'ok']);
return $next($request);
}
}
return response()->json(['status'=>'notAdmin']);
}
}
if(Auth::user()->role == 'administrator')
の部分で、ユーザーがadministrator
かどうかを判断している。
trueなら次の処理(apiを実行)する。
そうじゃないなら'status'=>'notAdmin'
と結果を返してそこで終わる。
カーネルに登録する
//プロジェクトディレクトリ/app/Http/Kernel.php
//中略
protected $routeMiddleware = [
'auth' => \\App\\Http\\Middleware\\Authenticate::class,
実行//追記
'auth.basic' => \\Illuminate\\Auth\\Middleware\\AuthenticateWithBasicAuth::class,
'cache.headers' => \\Illuminate\\Http\\Middleware\\SetCacheHeaders::class,
'can' => \\Illuminate\\Auth\\Middleware\\Authorize::class,
'guest' => \\App\\Http\\Middleware\\RedirectIfAuthenticated::class,
'password.confirm' => \\Illuminate\\Auth\\Middleware\\RequirePassword::class,
'signed' => \\Illuminate\\Routing\\Middleware\\ValidateSignature::class,
'throttle' => \\Illuminate\\Routing\\Middleware\\ThrottleRequests::class,
'verified' => \\Illuminate\\Auth\\Middleware\\EnsureEmailIsVerified::class,
];
'auth' => \\App\\Http\\Middleware\\Authenticate::
を追記。
これにより、api.phpから呼び出せるようになる。
ミドルウェアを通るようにapi.phpを編集
//api.php
Route::middleware('role')->group(function(){
Route::get('/hoge', [HogeController::class, 'index']);//管理者だけが実行できるapi
});
明らかにミドルウェアを通っていないような挙動になってしまう場合
なんか間違っててもエラーで止まらずに素通ししてしまうパターンがある。
dd()をミドルウェアの中に書いて切り分けしてみたら、止まらなかった!みたいな。
カーネルに書いているパスが間違っている
'role'=> \App\Http\Middleware\RoluAuthenticate::class,
api.phpにてrole
という名称でRoleAuthenticate
middlewareを呼び出したいのに、
Kernel.phpに記載しているファイル名がRoluAuthenticateになっているなどの場合。
また、ファイルを配置した場所によってもちゃんとパスがあっているかを確認すべき。
ミドルウェアのクラス名が間違っている
class RoleAuthenticate{・・・}
みたいな記述が10行目ぐらいにあると思うが、そこの名称がファイル名と一致しているかを確認。
ミドルウェアの使い方について
普段なんとなくでミドルウェアを使ってたけど、santctumの認証ガードも今回解説した書き方にに則っている。
Route::middleware('auth:sanctum')->group(function(){
Route::get('/hoge', [HogeController::class, 'index']);
});
↓公式ドキュメント
管理者にしか実行させたくないAPIって、例えばどんなん?
投稿に承認機能を設けていて、その承認を行う処理
など。
承認ボタンをそもそも管理者にしか表示させないような仕組みにしていても、裏側から一般ユーザーに実行されたらあかんやん?
そんなかんじ。