You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 11:53:20