修改Laravel+Inertia登录表单的Session错误提示行为
问题描述
我有一个包含username和password字段的登录表单,两个div分别用于展示对应字段的错误信息,且两个输入均为必填项。目前使用session存储错误信息,但存在问题:当凭证无效时,无论用户名还是密码错误,都只会在form.errors.username返回统一提示These credentials do not match our records.。我需要修改为:
- 用户名错误时,
form.errors.username返回用户名无效 - 密码错误时,
form.errors.password返回密码错误
当前代码:
Controller 代码
public function store(LoginRequest $request): RedirectResponse { $request->authenticate(); $request->session()->regenerate(); return redirect()->intended(RouteServiceProvider::HOME); }
登录表单(Vue + Inertia)代码
<script setup> import { Head, useForm, Link } from "@inertiajs/vue3"; const form = useForm({ username: "", password: "", remember: false, }); const submit = () => { form.post(route("login"), { onFinish: () => form.reset("password"), }); }; </script> <template> <form @submit.prevent="submit"> <div class="form-outline mb-4"> <label class="form-label" for="username">Username</label> <input type="username" id="username" class="form-control border rounded" v-model="form.username" required /> <div v-show="form.errors.username"> <p class="text-danger">{{ form.errors.username }}</p> </div> </div> <div class="form-outline mb-4"> <label class="form-label" for="password">Password</label> <input type="password" id="password" class="form-control border rounded" v-model="form.password" required /> <div v-show="form.errors.password"> <p class="text-danger">{{ form.errors.password}}</p> </div> </div> <button :class="{ 'opacity-25': form.processing }" :disabled="form.processing" type="submit" class="btn formBtn text-white w-100 mb-4" > Login </button> </form> </template>
解决方案
默认Laravel的登录验证会返回统一错误,无法区分用户名或密码错误,需要自定义验证逻辑:
1. 修改LoginRequest的验证逻辑
找到app/Http/Requests/Auth/LoginRequest.php,重写authenticate方法,分别校验用户名和密码,抛出对应字段的错误:
<?php namespace App\Http\Requests\Auth; use App\Models\User; use Illuminate\Auth\Events\Lockout; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\RateLimiter; use Illuminate\Support\Str; use Illuminate\Validation\ValidationException; class LoginRequest extends FormRequest { // 保留原有默认方法 public function authenticate() { $this->ensureIsNotRateLimited(); // 检查用户名是否存在 $user = User::where('username', $this->username)->first(); if (!$user) { RateLimiter::hit($this->throttleKey()); throw ValidationException::withMessages([ 'username' => __('用户名无效'), ]); } // 检查密码是否匹配 if (!Hash::check($this->password, $user->password)) { RateLimiter::hit($this->throttleKey()); throw ValidationException::withMessages([ 'password' => __('密码错误'), ]); } RateLimiter::clear($this->throttleKey()); Auth::login($user, $this->boolean('remember')); } // 保留原有默认方法 }
2. 说明
- 先查询用户名对应的用户,不存在则给
username字段绑定错误提示 - 用户存在但密码不匹配时,给
password字段绑定错误提示 - 保留了默认的频率限制逻辑,防止暴力破解
- Inertia的
useForm会自动捕获后端抛出的ValidationException错误,绑定到对应字段的form.errors中,前端无需额外修改即可展示对应错误提示
内容的提问来源于stack exchange,提问作者ahmad kharabsheh
相关产品推荐
相关产品推荐

