middleware('guest')->except('logout'); を使用していた } /** * ログインフォームを表示 * * @return \Illuminate\View\View */ public function showLoginForm() { return view('auth.login'); } /** * ログインリクエストを処理 * Laravel 12変更点:AuthenticatesUsersトレイトを使わず独自実装 * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\Http\JsonResponse */ public function login(Request $request) { $this->validateLogin($request); // ログイン試行回数制限チェック if ($this->hasTooManyLoginAttempts($request)) { $this->fireLockoutEvent($request); return $this->sendLockoutResponse($request); } // ログイン認証試行 if ($this->attemptLogin($request)) { return $this->sendLoginResponse($request); } // ログイン失敗時の処理 $this->incrementLoginAttempts($request); return $this->sendFailedLoginResponse($request); } /** * ログインリクエストのバリデーション * * 仕様上の入力名(フォーム側)は ope_id / ope_pass のまま維持し、 * 内部の認証キーは login_id に寄せる(login_id 統一)。 * * @param \Illuminate\Http\Request $request * @return void */ protected function validateLogin(Request $request) { // 個別未入力メッセージ(仕様1,2) $request->validate([ 'ope_id' => 'required|string', // フォームの入力名は現状維持(実体は login_id) 'ope_pass' => 'required|string', ], [ 'ope_id.required' => 'ログインIDが未入力です。', 'ope_pass.required' => 'パスワードが未入力です。', ]); } /** * ログイン認証を試行 * * * - 画面入力(ope_id)= DBの login_id として扱う * - 退職フラグチェックも login_id で取得して判定する * * @param \Illuminate\Http\Request $request * @return bool */ protected function attemptLogin(Request $request) { // 先にIDのみでオペレータ取得して退職フラグを確認(仕様5-1) $loginId = $request->input('ope_id'); // 入力名は ope_id だが中身は login_id $operator = \App\Models\Ope::where('login_id', $loginId)->first(); if ($operator && (int)($operator->ope_quit_flag) === 1) { // 退職扱いは認証失敗と同じメッセージ(仕様5-1 と 3/4 統一表示) return false; } // 認証実行(credentials() で login_id / password を渡す) return Auth::attempt($this->credentials($request), false); } /** * 認証用の資格情報を取得 * * * - 認証IDを login_id に統一 * - パスワード入力(ope_pass)は Auth 側の password にマッピング * * @param \Illuminate\Http\Request $request * @return array */ protected function credentials(Request $request) { return [ 'login_id' => $request->input('ope_id'), // フォーム入力(ope_id)→ DB列 login_id 'password' => $request->input('ope_pass'), // フォーム入力(ope_pass)→ 認証用 password ]; } /** * ログイン成功時のレスポンス * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse */ protected function sendLoginResponse(Request $request) { $request->session()->regenerate(); $this->clearLoginAttempts($request); // 仕様5: ログインIDをセッション保持 // ここで保持する値も login_id(入力名は ope_id のまま) $request->session()->put('login_ope_id', $request->input('ope_id')); return redirect()->intended($this->redirectTo); } /** * ログイン失敗時のレスポンス * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\RedirectResponse */ protected function sendFailedLoginResponse(Request $request) { // 画面側のエラー表示キーは仕様に合わせて ope_id のまま throw ValidationException::withMessages([ 'ope_id' => [trans('auth.failed')], ]); } /** * ログアウト処理 * Laravel 12変更点:セッション無効化処理を追加 * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse */ public function logout(Request $request) { Auth::logout(); // Laravel 12: セッション無効化とトークン再生成を明示的に実行 $request->session()->invalidate(); $request->session()->regenerateToken(); return redirect('/login'); } /** * ログイン試行回数が上限を超えているかチェック * Laravel 12変更点:RateLimiterファサードを使用 * * @param \Illuminate\Http\Request $request * @return bool */ protected function hasTooManyLoginAttempts(Request $request) { return RateLimiter::tooManyAttempts( $this->throttleKey($request), 5 ); } /** * ログイン試行回数をインクリメント * * @param \Illuminate\Http\Request $request * @return void */ protected function incrementLoginAttempts(Request $request) { RateLimiter::hit( $this->throttleKey($request), 60 ); } /** * ログイン試行回数制限をクリア * * @param \Illuminate\Http\Request $request * @return void */ protected function clearLoginAttempts(Request $request) { RateLimiter::clear($this->throttleKey($request)); } /** * ロックアウト発生時のイベント処理 * * @param \Illuminate\Http\Request $request * @return void */ protected function fireLockoutEvent(Request $request) { // 必要に応じてイベントを発火 } /** * レート制限用のスロットルキーを取得 * * * - 画面入力名は ope_id のまま * - ただし内容は login_id を想定(ログインID文字列) * * @param \Illuminate\Http\Request $request * @return string */ protected function throttleKey(Request $request) { return Str::lower($request->input('ope_id')) . '|' . $request->ip(); } /** * ロックアウト時のレスポンス * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\RedirectResponse */ protected function sendLockoutResponse(Request $request) { $seconds = RateLimiter::availableIn( $this->throttleKey($request) ); // 画面側のエラー表示キーは仕様に合わせて ope_id のまま throw ValidationException::withMessages([ 'ope_id' => [trans('auth.throttle', ['seconds' => $seconds])], ]); } }