【Laravel8.x】guardと自作middlewareを使って認証APIを作ってみた。単一テーブルマルチ認証?

今回はLaravel API認証サービスのsanctumやpassportを使わないで認証を行ってみようと思います!

今回はmiddlewareも自作してオレオレ認証も作っていきます!

やりたいことはguardを使った通常ログインとuserテーブルにis_adminカラムを追加してフラグとして利用してtrue/falseの値で利用できるroutingを変えていこうと思います!

そのためにもmiddlewareも自作してみます。

Laravel8.xはすでにインストールされている前提で進めていきます。

Modelとusersテーブルの修正

usersテーブルの修正

seederでダミーデータを作る前に、usersテーブルの修正をしておきます。

{プロジェクト名}/database/migrations/yyyy_mm_dd_xxxxxx_create_users_table.php

<?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->string('api_token', 80)->unique()->nullable()->default(null)->comment('guardが参照するapi_token'); $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)

追加するのはis_adminとapi_tokenカラムです。

Modelの修正

次にモデル。

{プロジェクト名}/app/Models/User.php

//$fillable内にapi_tokenとis_adminを追加 protected $fillable = [ 'name', 'email', 'password', 'api_token', //add 'is_admin', //add ];
Code language: PHP (php)

これでOKじゃあダミーデータの作成へ。

ダミーデータの作成

まず初めにログインするユーザのダミーデータを作成。

参考↓

https://yama-weblog.com/create-dummy-data-using-seeder-in-laravel8/

$ php artisan make:seeder UserTableSeeder

UserTableSeederの修正
{プロジェクト名}/database/seeders/UserTableSeeder.php

<?php namespace Database\Seeders; use Illuminate\Database\Seeder; use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; class UserTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { //userのダミーデータを2つ作成 DB::table('users')->insert([ [ //admin権限を持つユーザー 'name' => 'test1', 'email' => 'test1@test', 'is_admin' => true, 'password' => bcrypt('test'), 'api_token' => Str::random(60), ], [ //admin権限を持たないユーザー 'name' => 'test2', 'email' => 'test2@test', 'is_admin' => false, 'password' => bcrypt('test'), 'api_token' => Str::random(60), ], ]); } }
Code language: HTML, XML (xml)

そしたら、DatabaseSeeder.phpに以下を追加しましょう。

{プロジェクト名}/database/seeders/DatabaseTableSeeder.php

public function run() { // \App\Models\User::factory(10)->create(); //seederの呼び出しを行う。 $this->call([ UserTableSeeder::class, ]); }
Code language: PHP (php)
php migration refresh php artisan db:seed
Code language: CSS (css)

これでOKなはず!ではGuardの設定をしていきます。

guardの設定とログイン

configの設定

まずはconfigの設定から。

guardを触るときは以下から操作します。

以下の記事はguardを利用する際には参考にさせていただきました。

https://zenn.dev/ad5/articles/48671b32c89897

{プロジェクト名}/config/auth.php

'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], //以下が追加 'api' => [ 'driver' => 'token', //usersテーブルのtoken_apiを参照 'provider' => 'users', ], ],
Code language: PHP (php)

そしたらログインのAPIを作っていきます。

Login API作成

参考

https://reffect.co.jp/laravel/laravel-api-authentication-token-base#users

php artisan make:controller Auth/LoginController

{プロジェクト名}/app/Http/Controllers/Auth/LoginController.php

<?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use Illuminate\Http\Request; //add use Illuminate\Support\Facades\Auth; use App\Models\User; use \Symfony\Component\HttpFoundation\Response; use Illuminate\Support\Str; class LoginController extends Controller { public function login(Request $request) { $credentials = $request->only(['email', 'password']); //requestからemail,passwordだけ取ってくる。 $guard = $request->guard; //attempt()でユーザを認証する。 if(Auth::guard($guard)->attempt($credentials)) { //ログインをする度にapi_tokenのアップデート $user_info = User::whereEmail($request->email)->first(); //userのメールアドレスの取得 $user_id = $user_info->id; //usersテーブルから対象userを見つけてapi_tokenを再生成する。 $user = User::find($user_id); $user->api_token = Str::random(60); $user->save(); //loginが成功するとtokenと共に情報をjsonで返す。 return response()->json([ 'token' => $user->api_token, 'id' => $user->id, 'name' => $user->name, 'email' => $user->email, ], Response::HTTP_OK); } return 'login failed!'; } }
Code language: HTML, XML (xml)

ログインをするときにapi_tokenを再生成するようになっています!

ただ、このままだったらただのログイン機能で終わってしまうので、usersテーブルのカラムの値によって振り分けることができないので、そこの振り分けができるようにします。

そのためにmiddlewareを作成していきます~

middlewareの作成

参考ブログ

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

ほい、では作っていきます。

php artisan make:middleware AdminAuth
Code language: CSS (css)

{プロジェクト名}/app/Http/Middleware/AdminAuth.phpの修正。

<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; class AdminAuth { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ //usersテーブルのis_adminを見て管理者権限があるかどうかを調べる。 public function handle(Request $request, Closure $next) { //auth()->check() 認証済かどうか //auth()->user()->is_admin == true adminかどうか if(auth()->check() && auth()->user()->is_admin == true) { return $next($request); } //エラーメッセージ abort(403, 'This action is unauthorized.'); } }
Code language: HTML, XML (xml)

ほいー、middlewareができました。自作ですね。

ただ、このままだとmiddlewareは使えないので登録しますね。

{プロジェクト名}/app/Http/Kernel.phpのprotected $routeMiddlewareに以下を追加します。

'admin_auth' => \App\Http\Middleware\AdminAuth::class
Code language: PHP (php)

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

よし、これで最後に答え合わせです。

routing設定

ではrouteを書いていきます!
{プロジェクト名}/route/api.php

<?php use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; //追加 use App\Http\Controllers\Auth\LoginController; /* |-------------------------------------------------------------------------- | API Routes |-------------------------------------------------------------------------- | | Here is where you can register API routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | is assigned the "api" middleware group. Enjoy building your API! | */ //Route::middleware('auth:sanctum')->get('/user', function (Request $request) { // return $request->user(); //}); Route::post('login', [LoginController::class, 'login']); // admin権限のあるユーザの操作 Route::middleware('auth:api', 'admin_auth')->group(function(){ Route::get('/admin', function(){ return 'you are admin user!'; }); }); // user権限、admin権限のあるユーザの操作 Route::middleware('auth:api')->group(function(){ Route::get('/user', function(){ return 'you are member user!'; }); });
Code language: HTML, XML (xml)

ほい!こんな感じで書いてみました!

初めにログインして、取得したtokenを持って、adminかuserにアクセスしてみましょう!

localhost/api/login  (passwordとemailをPOSTで投げてtokenを取得) localhost/api/admin  (is_admin=trueのユーザのtokenを持ってGETでアクセスする falseのuserはアクセスできない) localhost/api/user  (loginできたuserのtokenを持っていると誰でもGETでアクセスが可能)

POSTMANで試すといいと思います!

まとめ

やり方さえわかったらすぐにできる。

ただ、sanctumとか使った方が簡単にはできるかと思います~

手順も少ないしね。

コメントを残す

メールアドレスが公開されることはありません。

CAPTCHA