Node.js+MongoDB+bcrypt.js登录系统密码验证异常问题排查
登录验证异常:所有用户只能用第一个用户的密码登录的问题修复
问题根源
你的登录逻辑存在前后端字段不匹配的错误,导致查询用户时始终返回数据库中的第一个用户:
- 用户模型(
user.js)中存储用户名的字段是name - 注册流程正常:后端将前端传入的
username存入name字段 - 但登录时,前端(
scriptLogin.js)发送的请求体里,用户名对应的字段是name,而后端登录接口(server.js)却尝试用username字段查询数据库。此时req.body.username为undefined,User.findOne({username: undefined})会匹配所有无username字段的文档(即所有用户),mongoose默认返回第一个匹配结果,因此无论输入哪个用户名,后端都在和第一个用户的密码做校验。
修复方案(推荐第一种)
方案一:对齐前后端查询字段
直接修改后端登录接口,使用数据库中实际存储的name字段查询用户:
// server.js 中 /api/login 接口修改 app.post('/api/login', async (req, res) => { // 解构前端传入的name字段,重命名为username方便后续使用 const {name: username, password} = req.body // 使用name字段查询对应用户 const user = await User.findOne({name: username}).lean() if (!user) { return res.status(400).json({error: 'Invalid username'}) } if (await bcrypt.compare(password, user.password)) { const token = jwt.sign({id: user._id, username: username}, JWT_SECRET) console.log(token) // 建议将token返回给前端,方便后续鉴权 return res.status(200).json({status: 200, data: token}) } else { res.status(400).json({status: 400, error: 'Invalid password'}) } })
方案二:统一字段名为username(可选)
如果希望全程使用username作为用户名字段,需同步修改模型、注册和登录逻辑:
- 修改用户模型(
./models/user.js):
const mongoose = require('mongoose') const UserSchema = new mongoose.Schema({ username: { type: String, required: true, unique: true }, password: { type: String, required: true } }) module.exports = mongoose.model('User', UserSchema)
- 修改注册接口(
server.js)的创建逻辑:
const response = await User.create({ username: username, password: hashedPassword })
- 修改前端登录请求(
./public/scriptLogin.js)的字段名:
body: JSON.stringify({ username: username, // 把name改成username password: password })
- 后端登录接口保持
const {username, password} = req.body和User.findOne({username}).lean()即可。
修复完成后,重新注册用户测试,每个用户的密码都能正确完成验证。
内容的提问来源于stack exchange,提问作者anousheh21
相关产品推荐
相关产品推荐

