【Laravel8.x】Sanctumを使ってroutingで権限管理してみた。単一テーブルマルチログイン?

今回はSanctumを使って行きます。

routingでどのユーザがどんな処理ができるのか等を制限していきます!

controllerにgateを使って書いていく方法もありますが、なかなか管理も難しいですしroutingを一目見ただけで誰が、どんな事をできるのかを知りたいときには不便だと思います。

では、進めていきます。

参考ブログ、資料は以下です。

https://blog.capilano-fw.com/?p=6121

https://readouble.com/laravel/8.x/ja/sanctum.html?header=%25E3%2583%2588%25E3%2583%25BC%25E3%2582%25AF%25E3%2583%25B3%25E3%2582%25A2%25E3%2583%2593%25E3%2583%25AA%25E3%2583%2586%25E3%2582%25A3%25E3%2583%259F%25E3%2583%2589%25E3%2583%25AB%25E3%2582%25A6%25E3%2582%25A7%25E3%2582%25A2

まず初めに。

まず初めに簡単な認証APIを作っていきます。

https://yama-weblog.com/using-sanctum-create-auth-api-in-laravel8/

上記の作業が完了した前提で進めます。(※Sanctumを入れて、認証APIができるまでを想定)

権限管理をしたいのでユーザテーブルには”is_admin”カラムを追加しますね。

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->boolean('is_admin')->default(false)->comment('trueだとadmin権限を持つ');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}
Code language: HTML, XML (xml)

ほい、では進めていきましょう!

LoginControllerの修正

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

//以下より追加
//-----------------------------------
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Validation\ValidationException;
use App\Models\User;
use \Symfony\Component\HttpFoundation\Response;

class LoginController extends Controller
{
    public function login(Request $request)
    {
        //バリデーション
        $credentials = $request->validate([
            'email' => 'required|email',
            'password' => 'required'
        ]);

        //login処理
        if (Auth::attempt($credentials)) {
            $user = User::whereEmail($request->email)->first(); //トークンの作成と取得

            //tokenを取得するユーザの権限を設定する。
            if ($user->is_admin == true) {
                $abilities = ['*'];
            }else{
                $abilities = ['user'];
            }

            $user->tokens()->delete();
            $token = $user->createToken("login:user{$user->id}", $abilities)->plainTextToken; //第二引数にabilities(userの権限を渡す。)

            //ログインが成功するとtokenを返す。
            return response()->json(['token' => $token], Response::HTTP_OK);
        }

        return response()->json('Can Not Login.', Response::HTTP_INTERNAL_SERVER_ERROR);
    }
}Code language: HTML, XML (xml)

今回はユーザの権限を以下のようにします。

  • フルアクセス= *
  • ユーザーアクセス= user
            $user = User::whereEmail($request->email)->first(); //トークンの作成と取得

            //tokenを取得するユーザの権限を設定する。
            if ($user->is_admin == true) {
                $abilities = ['*'];
            }else{
                $abilities = ['user'];
            }Code language: PHP (php)

ここでusersテーブルのis_adminカラムを見てtureだったらフルアクセス権限、falseだったらuser権限を$abilities変数に入れます。

$token = $user->createToken("login:user{$user->id}", $abilities)->plainTextToken; Code language: PHP (php)

createToken()メソッドの第二引数に権限を入れることで、personal_access_tokensテーブルのabilitiesカラムに引数で渡したものが入れられます。

Sanctumでは、トークンに「アビリティ」を割り当てることができます。アビリティはOAuthの「スコープ」と同様の目的を果たします。能力の文字列配列をcreateTokenメソッドの2番目の引数として渡すことができます。

 参考→  https://readouble.com/laravel/8.x/ja/sanctum.html?header=%25E3%2583%2588%25E3%2583%25BC%25E3%2582%25AF%25E3%2583%25B3%25E3%2581%25AE%25E3%2582%25A2%25E3%2583%2593%25E3%2583%25AA%25E3%2583%2586%25E3%2582%25A3

これでログインすることで権限が渡されます。

routingで管理

先ほど作成した権限をroutingで管理します。

Route::post('/login', [LoginController::class, 'login']);// ログイン

//admin権限のあるユーザ
Route::middleware('auth:sanctum', 'abilities:*')->group(function(){
    Route::get('/admin', function(){
        return 'you are admin user';
    });
});

//user権限のあるユーザ
Route::middleware('auth:sanctum', 'abilities:user')->group(function(){
    Route::get('/user', function(){
        return 'you are member user';
    });
});Code language: PHP (php)

ほい、こんな感じで、middlewareに’abilities:○○○○’を追加します。

//sanctumによって認証されている。
'auth:sanctum'

//personal_access_tokensテーブルのabilitiesカラムを見ている。
'abilities:user'Code language: JavaScript (javascript)

ただ、これだけではabilitiesは使えないので、アプリケーションの app/Http/Kernel.php ファイルの $routeMiddleware プロパティに以下のミドルウェアを追加します。

app/Http/Kernel.php

'abilities' => \Laravel\Sanctum\Http\Middleware\CheckAbilities::class,
'ability' => \Laravel\Sanctum\Http\Middleware\CheckForAnyAbility::class,Code language: PHP (php)

これで使えるようになりました!

おおー、こんな感じで簡単に割り振れることができるのね。

sanctum優秀ですな。

sanctumの複数指定

ちなみに、sanctumのアビリティを複数指定するときは以下

—両方を持っている時 (and条件)—

 // トークンは"check-status"と"place-orders"アビリティの"両方"を持っている
Route::get('/orders', function () {
})->middleware(['auth:sanctum', 'abilities:check-status,place-orders']);Code language: PHP (php)

—どちらかを持っている時 (or条件)—

Route::get('/orders', function () {
// Token has the "check-status" or "place-orders" ability...
})->middleware(['auth:sanctum', 'ability:check-status,place-orders']);Code language: PHP (php)

and条件=abillities
or条件=ability

ということになっているようですね。

公式サイト←を引用しました

まとめ

sanctumを使うと簡単にはできるけど、今後オリジナルで改造していくのとかは大変そう。

理解理解、深めていく。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA