注册成功后登录提示「用户不存在」及注册按钮双击问题排查
问题原因分析
1. 登录提示「用户不存在」但注册提示「用户已存在」
前端登录请求的异步状态问题
如果你的setUser是React等框架的异步状态更新方法,它不会立即修改user变量的值。你在调用setUser后立刻发起axios.post请求,此时发送的user还是更新前的旧值(可能是空对象或错误邮箱),导致后端接收到的邮箱不正确,自然查不到用户。
后端登录接口的逻辑漏洞
登录接口中,查询不到用户时返回了「用户不存在」的响应,但没有终止后续代码执行:
if (!user) res.status(400).json({ msg: "User does not exist" }); // 未添加return,后续代码会继续执行 bcrypt.compare(password, user.password) // user为undefined,会抛出错误
虽然用户会收到「用户不存在」的提示,但服务器会额外抛出错误,可能掩盖真实问题。另外,登录接口返回的user.name字段错误——你的注册逻辑和User模型用的是username,这里应该返回user.username,否则会得到undefined。
注册接口的冗余判断隐患
注册接口中的if (password)判断完全多余:如果密码为空,后续的bcrypt.hash会报错,且此时你没有返回任何响应,会导致请求挂起,前端一直等待结果。
2. 注册按钮需双击才响应
大概率是未阻止表单的默认提交行为。点击注册按钮时,浏览器会触发表单的默认提交事件,导致页面刷新,中断axios请求。第一次点击时请求被中断,第二次点击时表单状态已被处理,请求才成功发送。
修复建议
修复登录请求的异步问题
直接使用表单值发起请求,跳过状态更新的异步延迟:
const loginData = { email: form.email.value, password: form.password.value }; axios.post("http://localhost:4000/login", loginData) .then(res => console.log(res)) .catch(err => console.log("An error occured: ", err.response));
如果依赖状态更新,可使用状态回调(以React为例):
setUser({ email: form.email.value, password: form.password.value }, () => { axios.post("http://localhost:4000/login", user) .then(res => console.log(res)) .catch(err => console.log("An error occured: ", err.response)); });
修复后端登录接口逻辑
添加return终止无效分支的代码执行,修正返回字段并捕获错误:
module.exports.login = async (req, res) => { const { email, password } = req.body; User.findOne({ email }) .then(user => { if (!user) { return res.status(400).json({ msg: "User does not exist" }); } bcrypt.compare(password, user.password) .then(matched => { if (!matched) { return res.status(400).json({ msg: "Invalid credentials" }); } jwt.sign( { id: user._id }, config.get('jwtsecret'), { expiresIn: 3600 }, (err, token) => { if (err) return res.status(500).json({ msg: "Server error" }); res.send({ token, user: { id: user._id, username: user.username, // 修正为username字段 email: user.email } }); } ) }) .catch(err => res.status(500).json({ msg: "Server error" })); }) .catch(err => res.status(500).json({ msg: "Server error" })); };
修复注册按钮双击问题
在表单提交或按钮点击事件中阻止浏览器默认行为:
const handleRegister = (e) => { e.preventDefault(); // 阻止默认表单提交 axios.post("http://localhost:4000/register", user) .then(res => { console.log(res); setRegistered(true); }) .catch(err => { console.log("An error occured: ", err.response.data); }); };
修复注册接口冗余判断
移除多余的密码判断,添加参数校验和错误捕获:
module.exports.register = (req, res) => { const { username, email, password } = req.body; // 先校验必填字段 if (!username || !email || !password) { return res.status(400).json({ msg: "请填写所有字段" }); } const saltRounds = 10; User.findOne({ email }) .then(user => { if (user) { return res.status(400).send("User already exists."); } bcrypt.genSalt(saltRounds, function (err, salt) { if (err) return res.status(500).json({ msg: "Server error" }); bcrypt.hash(password, salt, function (err, hash) { if (err) return res.status(500).json({ msg: "Server error" }); const newUser = new User({ username, email, password: hash }); newUser.save() .then(user => { jwt.sign( { id: user._id }, config.get('jwtsecret'), { expiresIn: 3600 }, (err, token) => { if (err) return res.status(500).json({ msg: "Server error" }); res.send("User registered.") } ) }) .catch(err => res.status(500).json({ msg: "Server error" })); }); }); }) .catch(err => res.status(500).json({ msg: "Server error" })); };
内容的提问来源于stack exchange,提问作者Vedanti Jadhav
相关产品推荐
相关产品推荐

