React JS重置密码请求返回400(Bad Request)错误排查求助
问题描述
我基于React实现了密码重置功能,流程为:用户提交邮箱后会收到包含token与邮箱的重置链接,页面通过useSearchParams获取链接中的email和token参数,发起POST请求至/api/accounts/reset-password接口完成密码重置。但控制台提示错误:
Failed to load resource: the server responded with a status of 400 (Bad Request)
我确认问题出在客户端,以下是我的代码:
import { useState } from 'react'; import { useSearchParams } from 'react-router-dom'; import api from '../contexts/BaseUrl'; function ResetPassword(){ const [searchParams] = useSearchParams(); const [password, setPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState(''); const [success, setSuccess] = useState(null); const [errMsg, setErrMsg] = useState("") const email = searchParams.get('email'); const token = searchParams.get('token'); const handleSubmit = async (e) => { e.preventDefault(); try{ const response = await api.post( '/api/accounts/reset-password', JSON.stringify({password, confirmPassword, email, token}), { headers:{ "Accept" : "application/json", "Content-Type" : "application/json", } }); setPassword(""); setConfirmPassword(""); setSuccess(true); }catch(err){ setPassword(""); setConfirmPassword(""); setSuccess(false); if(!err?.response){ setErrMsg('No Server Response') }else{ setErrMsg('Failed changing password!'); } } } return ( <div> <div>Email : {email}</div> <button onClick={() => console.log(tokenGet)}>Token</button> <form className="userContent2" onSubmit={handleSubmit} > <label>New Password: </label> <input type="password" pattern = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$" value = {password} required onChange={event => { setPassword(event.target.value); if (event.target?.validity?.patternMismatch) { event.target?.setCustomValidity('Min - 8 chars,1 Uppercase, 1 Lowercase, 1 number, 1 special character '); } else { event.target?.setCustomValidity(''); } }} /> <label>Confirm New Password: </label> <input type="password" pattern = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$" value = {confirmPassword} required onChange={event => { setConfirmPassword(event.target.value); if (event.target?.value !== password) { event.target?.setCustomValidity('Password doesn\'t match'); } else { event.target?.setCustomValidity(''); } }} /> <button className='userButton'>Save</button> {!success && <div className='error'>{err}</div>} {success && <div className='success'>Password Successfully Changed!</div>} </form> </div> );} export default ResetPassword;
问题排查与修复点
冗余请求参数触发后端校验失败
密码确认是前端验证逻辑,后端重置接口通常只需要password、email、token三个参数。你传入的confirmPassword属于冗余参数,会触发后端参数校验返回400,需要从请求体中移除。不必要的JSON序列化导致格式异常
如果你的api实例基于Axios创建,Axios会自动将JavaScript对象序列化为JSON请求体,手动调用JSON.stringify反而可能导致格式错误,直接传入对象即可。错误提示变量引用错误
你定义的错误状态变量是errMsg,但渲染时用了未定义的err,导致错误信息无法显示,需修正为{errMsg},同时优化渲染逻辑,避免初始状态(success为null)时错误提示误显示。未提前拦截密码不一致的情况
虽然输入框有自定义校验,但在提交前手动做一次密码一致性检查,能提前拦截错误,减少无效请求。变量拼写错误
页面中的按钮点击事件用了未定义的tokenGet,需改为已定义的token,避免控制台出现额外错误。
修改后的关键代码示例
修正后的handleSubmit函数
const handleSubmit = async (e) => { e.preventDefault(); // 前端提前校验密码一致性 if (password !== confirmPassword) { setErrMsg('两次输入的密码不一致'); return; } try{ const response = await api.post( '/api/accounts/reset-password', {password, email, token}, // 移除confirmPassword,无需手动序列化 { headers:{ "Accept" : "application/json", "Content-Type" : "application/json", } }); setPassword(""); setConfirmPassword(""); setSuccess(true); setErrMsg(""); }catch(err){ setPassword(""); setConfirmPassword(""); setSuccess(false); if(!err?.response){ setErrMsg('无服务器响应') }else{ // 尝试获取后端返回的具体错误信息,提升调试效率 setErrMsg(err.response.data?.message || '密码修改失败!'); } } }
修正后的错误提示渲染
{success === false && <div className='error'>{errMsg}</div>} {success === true && <div className='success'>密码修改成功!</div>}
修正后的Token按钮
<button onClick={() => console.log(token)}>查看Token</button>
内容的提问来源于stack exchange,提问作者Ehtesam Fayek Utsho

