はじめに
普段はRailsで実装をしている私が、Laravelで認証機能を作成しました。
「LaravelでAPIモードの実装ってどうやるんだ??」と気になったこともあり、こちらの記事を作成しました。
(ログインのみの実装です)
Laravel初学者の方々への一助になれば幸いです。
開発環境
PHP 8.1.27
Laravel 10.46.0
実装
マイグレーション
説明の関係上、ログインに必要なカラムのみ以下に記載しています。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('email')->unique();
$table->string('password');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('users');
}
};
モデル
$fillableプロパティは、Eloquentモデルでマスアサインメントを行う際に許可される属性(カラム)を指定するためのプロパティです。
マスアサインメントとは、一度に複数の属性をまとめてモデルに設定することです。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
protected $fillable = [
'name',
'email',
'password',
];
protected $hidden = [
'password',
];
protected $casts = [
'password' => 'hashed',
];
}
コントローラー
response()->jsonメソッドでJSONを返します。
Attemptは基本的に、ユーザーが提供した資格情報を使用してユーザーのログインを試行します。
資格情報は、下記のコードの$credentialsにあたリます。
認証が成功した場合、attemptメソッドはtrueを返します。それ以外の場合は、falseを返します。
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\LoginRequest;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
class AuthenticatedSessionController extends Controller
{
public function store(LoginRequest $request): \Illuminate\Http\JsonResponse
{
try {
# emailとpasswordのキーを持つ連想配列から値を取り出して、credentials変数に代入する
$credentials = $request->only('email', 'password');
# credentials変数の情報を渡し、Authファサードを介してログイン処理を行う。DB内のユーザーと一致したらattemptでtrue、存在しなかったらfalseを返す。
if(Auth::attempt($credentials)) {
# ユーザーを認証する
$request->authenticate();
# セッションIDの発行
$request->session()->regenerate();
return response()->json([
'status' => 'success',
'message' => 'ログインが成功しました'
], 200);
} else {
return response()->json([
'status' => 'error',
'message' => 'ログインに失敗しました'
], 401);
}
} catch (\Illuminate\Auth\AuthenticationException $e) {
return response()->json([
'status' => 'error',
'message' => '予期せぬエラーが発生しました'
], 500);
}
}
}
ルーティング
storeメソッドを呼び出して、認証を行います。
authミドルウェアを使用することでセッションの有効性を確認し、新しいセッションを作成・更新します。
(Railsにもミドルウェアの概念があるが、Rackミドルウェアのスタック内で実行されているようです)
<?php
use App\Http\Controllers\Auth\AuthenticatedSessionController;
use Illuminate\Support\Facades\Route;
Route::post('/api/login', [AuthenticatedSessionController::class, 'store'])
->middleware('auth');
Seedデータ
ログインするためのユーザーの初期データです。
Hash::make~のパスワードハッシュ化の処理は手動で実装しています。
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use DateTime;
class UsersTableSeeder extends Seeder
{
public function run()
{
DB::table('users')->insert([
'name' => 'sample1',
'email' => 'sample1@example.com',
'password' => Hash::make('password'),
'created_at' => new DateTime(),
'updated_at' => new DateTime()
]);
}
}
結果
Postmanで動作確認を行いました。
手順
- Bodyタグのform-dataでemailとpasswordを入力する
- http://localhost/api/login でPOSTリクエストを送信する
- 「ログインに成功しました」といったメッセージがJSONで表示されれば成功です
- 違うメールアドレスかパスワードを入力してログインに失敗すればOKです
終わりに
今回は公式ドキュメントなどを見ながら、標準の認証機能を作成しました。
Laravel初学者なのでまだまだ理解が浅いですが、時間がある時にその他の実装方法も勉強していければと思います。
参考記事
Laravel 10.x 認証
Laravel 10.x ハッシュ(https://readouble.com/laravel/10.x/ja/authentication.html)
Laravel 10.x HTTPレスポンス
Laravel で認証パラメータを追加する
Auth::login() vs Auth::attempt()