为何在Express注册路由中调用Mongoose的find()方法无法正常生效?
问题排查与修复方案
核心错误点
- 错误使用
find()查询方法:User.find()返回的是匹配结果的数组,哪怕没有匹配到邮箱也会返回空数组[],而JS中空数组的布尔判断结果为true,所以!emailSearch永远为false,第一个if判断逻辑完全失效。 - 分支判断逻辑错误:原判断写为
if (!emailSearch || username !== null),使用了或逻辑,也就是说只要用户名不为空,哪怕邮箱已经存在,也会进入创建用户的分支,直接触发MongoDB的唯一键重复报错E11000。 - 分支优先级顺序错误:应该先校验必填参数是否缺失,再判断邮箱是否重复,原逻辑中如果用户名为空,会直接进入
else if (emailSearch)分支,错误返回“email already exists”。 - 额外安全隐患:代码中直接存储了用户明文密码,你已经生成了hash和salt,完全不需要存储明文密码,存在数据泄露风险。
- 状态码语义错误:参数错误、资源重复应该返回400状态码,404表示资源不存在,不符合业务语义。
修正后代码
const express = require("express"); const router = express.Router(); const SHA256 = require("crypto-js/sha256"); const encBase64 = require("crypto-js/enc-base64"); const uid2 = require("uid2"); const User = require("../models/User"); router.post("/user/signup", async (req, res) => { try { const { email, username, phone, password } = req.fields; // 先校验必填参数 if (!username || !email || !password) { return res.status(400).json({ message: "请填写必填参数(邮箱、用户名、密码)" }); } // 改用findOne查询,找不到返回null const existingUser = await User.findOne({ email: email }); // 邮箱已存在直接返回 if (existingUser) { return res.status(400).json({ message: "email already exists" }); } // 所有校验通过再生成密钥创建用户 const token = uid2(64); const salt = uid2(16); const hash = SHA256(password + salt).toString(encBase64); const newUser = new User({ email: email, account: { username: username, phone: phone, }, // 删掉明文password存储 token: token, hash: hash, salt: salt, }); await newUser.save(); res.status(200).json({ _id: newUser._id, token: newUser.token, account: newUser.account, }); } catch (error) { res.status(400).json({ error: error.message, }); } });
内容的提问来源于stack exchange,提问作者xiand3r
相关产品推荐
相关产品推荐

