用户登录接口返回错误userId问题求助(附相关代码)
问题排查与解决方案
问题根源
- 模型字段不匹配:后端通过
email: req.body.email查询用户,但你的UserSchema中未定义email字段(仅存在clubEmail),这会导致查询条件无法精准匹配目标用户,甚至返回数据库中第一个符合“无约束”条件的文档。 - 前后端密码字段名不一致:前端请求时传递的是
passwordHash: password,但后端验证时读取的是req.body.password,这会使bcrypt.compareSync的第一个参数为undefined。若数据库中存在密码哈希为空的用户,会意外通过验证并返回该用户。
修复步骤
1. 修正User模型(添加/调整登录标识字段)
如果登录使用的是用户个人邮箱,在Schema中添加email字段并设置唯一性约束:
const userSchema = mongoose.Schema({ email: { type: String, required: true, unique: true, // 确保邮箱唯一,避免重复匹配 minlength: 5, maxlength: 100 }, contactName: { type: String, required: true, minlength: 5, maxlength: 50 }, phone: { type: String, required: true, minlength: 5, maxlength: 50 }, passwordHash: { type: String, required: true, minlength: 5, maxlength: 1024 }, token: { type: String, }, isAdmin: { type: Boolean, default: false }, clubName: { type: String, required: true, }, clubAddress: { type: String, required: true, }, clubEmail: { type: String, required: true, }, clubPhone: { type: String, required: true, }, clubWebsite: { type: String, required: true, }, clubContact: { type: String, required: true, }, })
若登录使用的是
clubEmail,则将后端查询条件改为clubEmail: req.body.email,无需新增字段。
2. 修正前端请求的密码字段名
前端请求时传递password而非passwordHash,与后端接收字段保持一致:
const handleSubmit = () => { axios .post(`${baseURL}users/login`, { email: email, password: password, // 修正字段名 }) .then(res => { console.log('USER ID TOKEN', res.data.token); setbearerToken(res.data.token); AsyncStorage.setItem('bearerToken', res.data.token); const decoded = decode(res.data.token); setTokenID(decoded.userId); dispatch(setUser(res.data)); }); };
3. 添加日志辅助排查
在后端登录路由中添加日志,确认请求参数与查询结果:
router.post("/login", async (req, res) => { console.log("Login request email:", req.body.email); const user = await User.findOne({ email: req.body.email, }); console.log("Queried user:", user); const secret = process.env.SECRET; if (!user) { return res.status(400).send("the user not found!"); } if (user && bcrypt.compareSync(req.body.password, user.passwordHash)) { const token = jwt.sign( { userId: user.id, isAdmin: user.isAdmin, }, secret, { expiresIn: "1d" } ); res.status(200).send({ user: user.email, token: token }); } else { res.status(400).send("password is wrong!"); } });
4. 确保登录字段唯一性
在数据库中给登录标识字段(如email或clubEmail)创建唯一索引,避免多个用户使用同一标识导致查询错误。
内容的提问来源于stack exchange,提问作者Jason Byron Beedle
相关产品推荐
相关产品推荐

