はじめに
Laravel10ではbreeze
をインストールすることでログイン認証機能が一瞬で実装できる。すごい時代だ。
php artisan breeze:install
breezeはメールアドレスとパスワードで認証する仕組みになっているが、ネットに公開しないような、たとえば社内インフラとしてのアプリケーションを構築する場合はメールアドレスではなく社員IDなどテキストデータとパスワードでログインさせたい。仕様を変更したときの備忘録。
userテーブルに社員IDのカラムを設定する
vi database/migrations/2014_10_12_000000_create_users_table.php
以下のようにした。ここでは社員IDを格納するカラムをnum
としている。'user_id'とか'employee_id'とかにしとけば良かったなぁ。
public function up(): void
{
if (!Schema::hasTable('users')) {
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('num')->unique();
$table->string('name');
$table->string('email');
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
}
Viewのbladeを編集する
Laravel10のViewはLaravel bladeコンポーネント
で記述されており、Tailwind CSS
が使われているらしい。既存の項目を編集すると見た目や挙動が多少変わるので、それぞれのinput
タグのclass
に"h-10"を追記している。
スタイルを編集しているので、反映しないなぁってときは編集後に以下のコマンドを。
npm run build
登録画面の編集
vi resources/views/auth/register.blade.php
英語で表示される部分をついでに日本語にしています。
<x-guest-layout>
<form method="POST" action="{{ route('register') }}">
@csrf
<!-- Name -->
<div>
<x-input-label for="name" :value="__('名前')" />
<x-text-input id="name" class="block mt-1 w-full h-10" type="text" name="name" :value="old('name')" required autofocus autocomplete="name" />
<x-input-error :messages="$errors->get('name')" class="mt-2" />
</div>
<!-- Employee Number ここを追記しています -->
<div class="mt-4">
<x-input-label for="num" :value="__('社員ID')" />
<x-text-input id="num" class="block mt-1 w-full h-10" type="text" name="num" :value="old('num')" />
<x-input-error :messages="$errors->get('num')" class="mt-2" />
</div>
<!-- Email Address -->
<div class="mt-4">
<x-input-label for="email" :value="__('Email')" />
<x-text-input id="email" class="block mt-1 w-full h-10" type="email" name="email" :value="old('email')" required autocomplete="username" />
<x-input-error :messages="$errors->get('email')" class="mt-2" />
</div>
<!-- Password -->
<div class="mt-4">
<x-input-label for="password" :value="__('パスワード')" />
<x-text-input id="password" class="block mt-1 w-full h-10"
type="password"
name="password"
required autocomplete="new-password" />
<x-input-error :messages="$errors->get('password')" class="mt-2" />
</div>
~ 以下略 ~
ログイン画面の編集
vi resources/views/auth/login.blade.php
Email文字列をPOST
している部分をnum
に変更する。
<x-guest-layout>
<!-- Session Status -->
<x-auth-session-status class="mb-4" :status="session('status')" />
<form method="POST" action="{{ route('login') }}">
@csrf
<!-- Email Address -->
<div>
<x-input-label for="num" :value="__('社員ID')" />
<x-text-input id="num" class="block mt-1 w-full h-10" type="text" name="num" :value="old('num')" required autofocus autocomplete="username" />
<x-input-error :messages="$errors->get('num')" class="mt-2" />
</div>
<!-- Password -->
<div class="mt-4">
<x-input-label for="password" :value="__('パスワード')" />
<x-text-input id="password" class="block mt-1 w-full h-10"
type="password"
name="password"
required autocomplete="current-password" />
<x-input-error :messages="$errors->get('password')" class="mt-2" />
</div>
~ 以下略 ~
リクエスト処理の編集
認証のリクエスト処理で合っていたら、間違っていたら、の処理は以下のファイルが担当している。
vi app/Http/Requests/Auth/LoginRequest.php
'email'
と記述されている部分をすべて'num'
に変更する。
public function rules(): array
{
return [
'num' => ['required', 'string'],
'password' => ['required', 'string'],
];
}
public function authenticate(): void
{
$this->ensureIsNotRateLimited();
if (! Auth::attempt($this->only('num', 'password'), $this->boolean('remember'))) {
RateLimiter::hit($this->throttleKey());
throw ValidationException::withMessages([
'num' => trans('auth.failed'),
]);
}
RateLimiter::clear($this->throttleKey());
}
public function ensureIsNotRateLimited(): void
{
if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
return;
}
event(new Lockout($this));
$seconds = RateLimiter::availableIn($this->throttleKey());
throw ValidationException::withMessages([
'num' => trans('auth.throttle', [
'seconds' => $seconds,
'minutes' => ceil($seconds / 60),
]),
]);
}
public function throttleKey(): string
{
return Str::transliterate(Str::lower($this->input('num')).'|'.$this->ip());
}
次の部分を修正する事で、認証失敗時の返答を日本語化できる。
- 'num' => trans('auth.failed'),
+ 'num' => 'IDまたはパスワードが違います',
本当は言語設定ファイルを修正すれば良いらしいが、どこにあるんだ???
Controllerの編集
Controllerの一覧を見たとき、あまりにもメールに関するものが多くてダメかと思ったが1つ編集すれば大丈夫だった。
AuthenticatedSessionController.php EmailVerificationNotificationController.php NewPasswordController.php PasswordResetLinkController.php VerifyEmailController.php
ConfirmablePasswordController.php EmailVerificationPromptController.php PasswordController.php RegisteredUserController.php
RegisteredUserController.php
を編集する。
vi app/Http/Controllers/Auth/RegisteredUserController.php
'num'
の設定を追記する。'unique:'.User::class
が記述されていると重複があった場合にエラーとなる。max:
の値は長すぎてもアレなので適当に少なくしている。
public function store(Request $request): RedirectResponse
{
$request->validate([
'name' => ['required', 'string', 'max:96'],
'num' => ['required', 'string', 'max:6', 'unique:'.User::class],
'email' => ['required', 'string', 'email', 'max:96'],
'password' => ['required', 'confirmed', Rules\Password::defaults()],
]);
$user = User::create([
'name' => $request->name,
'num' => $request->num,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
参考