ラボ > Laravel、Lumen:セキュリティ絡み、ajax、api絡み、ユーザー認証関連

Laravel8 API認証 / Laravel Sanctum

APIで認証が必要。調べるとLaravel Sanctumってヤツを使うらしい

作成日:2023-09-04, 更新日:2023-09-05

基本

APIでの認証にはいくつかある。あるけど、Laravel8だと「Laravel Sanctum」ってのが用意されているとのコト。
「Laravel Sanctum」ってのを使ってAPIでの認証を実装する場合、「ステートレス認証」という方式になるそうだ。

私の環境

WIN+Docker+Ubuntuでlaravelを使うための作業メモ

流れ

参照: codelikes.com/use-laravel-sanctum

  1. Laravel Sanctumのインストールと有効化
  2. ルーティング設定
  3. コントローラー作成: 登録
  4. コントローラー作成: ログイン
  5. 確認(postmanってのを使う)

※ルーティング設定とコントローラー作成はどっちを先にしても良いと思う

Laravel Sanctumのインストールと有効化

Laravel Sanctumのインストール

すでにインスト済みなので、無視(未調査)

artisanコマンド叩いて、マイグレーション実行…という流れっぽい

Laravel Sanctumの有効化

すでに記載済みだったので内容の確認だけ。コメントされていたらコメント解除

▼app/Http/Kernel.php

~省略~
'api' => [
    \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, // ← 追加
    ~省略~
]
~省略~

▼app/Models/User.php

~省略~
use Laravel\Sanctum\HasApiTokens; // ← 追加
~省略~
class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable; // ← 「HasApiTokens」を追加
~省略~

ルーティング設定

▼routes/api.php

~省略~
use App\Http\Controllers;
~省略~

// ▼消しても良いけど、ひとまずコメント
// Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
//     return $request->user();
// });

Route::middleware('auth:sanctum')->group(function () { // 認証中のみ有効なページたち
    // Route::post('/logout', [Controllers\Api\LogoutController::class, 'do']); // ログアウト ← APIだからいらないかな?
    // Route::prefix('profile')->group(function(){ // ← いずれ作る予定だから下準備だけしておく
    //     Route::get('/', [Controllers\Api\ProfileController::class, 'index']);
    //     Route::post('do', [Controllers\Api\ProfileController::class, 'do']);
    // });
});

Route::post('/register', [Controllers\Api\RegisterController::class, 'do']);// ユーザー登録
Route::post('/login', [Controllers\Api\LoginController::class, 'do']);// ログイン

~省略~

コントローラー作成: 登録

ubuntuからartisanコマンドを叩く

xxxx$ ./vendor/bin/sail php artisan make:controller Api/RegisterController

→「app/Http/Controllers/Api/RegisterController.php」が作られる

app/Http/Controllers/Api/RegisterController.phpの修正

~ 省略 ~
// ▼追加分
use App\Providers\RouteServiceProvider;
use App\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use \Symfony\Component\HttpFoundation\Response;

class RegisterController extends Controller
{
    public function do(Request $request)
    {
        /** @var Illuminate\Validation\Validator $validator */
        $validator = Validator::make($request->all(), [
            'name' => 'required',
            'email' => 'required|email',
            'password' => 'required'
        ]);

        if ($validator->fails()) {
            return response()->json($validator->messages(), Response::HTTP_UNPROCESSABLE_ENTITY); // バリデーションエラーで422
        }

        User::create([
            'name' =>  $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        return response()->json('User registration completed', Response::HTTP_OK); // 200で返す
    }
}

コントローラー作成: ログイン

ubuntuからartisanコマンドを叩く

xxxx$ ./vendor/bin/sail php artisan make:controller Api/LoginController

→「app/Http/Controllers/Api/LoginController.php」が作られる

app/Http/Controllers/Api/LoginController.phpの修正

~ 省略 ~
// ▼追加分
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;
use App\Models\User;
use \Symfony\Component\HttpFoundation\Response;

class LoginController extends Controller
{
    public function do(Request $request)
    {
        $credentials = $request->validate([
            'email' => 'required|email',
            'password' => 'required'
        ]);

        if (Auth::attempt($credentials)) { // ログイン成功
            // 既存のトークンを削除
            $user = User::whereEmail($request->email)->first();
            $user->tokens()->delete();

            // トークンの生成して返す
            $token = $user->createToken("login:user{$user->id}")->plainTextToken;
            return response()->json(['token' => $token ], Response::HTTP_OK);
        }

        // ===============================
        // 以下、ログイン失敗時の処理
        return response()->json('User Not Found.', Response::HTTP_INTERNAL_SERVER_ERROR);
    }
}

確認(postmanってのを使う)

localhostで確認が面倒なので「postman」ってのを使う

ログイン後の確認

APIでログインしたらトークンが返ってくるのでそのトークンを使ってログインしている人用のAPIを叩いてみる

  1. ルーティング設定
  2. ubuntuからartisanコマンドを叩く
  3. コントローラーファイルの修正
  4. POSTMANで実行

ルーティング設定

▼routes/api.php

~ 省略 ~
Route::middleware('auth:sanctum')->group(function () { // 認証中のみ有効なページたち
    Route::post('/test', [Controllers\Api\TestController::class, 'index']); // テスト用に追加
    ~ 省略 ~
});
~ 省略 ~

ubuntuからartisanコマンドを叩く

コントローラーファイルを作成

xxxx$ ./vendor/bin/sail php artisan make:controller Api/TestController

→「app/Http/Controllers/Api/TestController.php」が作られる

コントローラーファイルの修正

▼app/Http/Controllers/Api/TestController.php

~ 省略 ~

// ▼追加分
use \Symfony\Component\HttpFoundation\Response;

class TestController extends Controller
{
    public function index(Request $request)
    {
        $response = array(
            'hoge' => '丸ごとシマウマ',
        );
        return response()->json($response, Response::HTTP_OK);
    }
}
~ 省略 ~

POSTMANで実行

ログインAPIを叩いたときのトークンを「authorization」の「Bearer」ってトコにセットしてアクセス

メモ

バリデーションエラー時はlaravelの標準設定としてTOPにリダイレクトしているとか…
後でバリデーションは自作するからカスタマイズはひとまず放置