Node.js中bcrypt密码匹配失败问题排查与解决求助
Node.js JWT + bcrypt 用户登录密码不匹配问题排查
问题背景
开发基于Node.js的用户认证系统,使用JWT和bcrypt实现注册与登录。注册功能正常完成,但使用注册时的相同密码登录,始终提示密码不匹配。
核心代码
认证控制器代码
const jwt = require('jsonwebtoken'); const bcrypt = require('bcrypt'); const User = require('../models/User'); // 注册新用户 const register = async (req, res, next) => { const { username, email, password, role = 'student' } = req.body; const saltRounds = 10; try { const hashedPassword = await bcrypt.hash(password, saltRounds); const user = new User({ username, email, password: hashedPassword, role }); await user.save(); res.json({ message: 'Registration successful' }); } catch (error) { next(error); } }; // 用户登录 const login = async (req, res, next) => { const { username, password } = req.body; try { console.log('Received login request:', req.body); if (!username || !password) { return res.status(400).json({ message: 'Username and password are required' }); } const user = await User.findOne({ username }); if (!user) { console.log('User not found'); return res.status(404).json({ message: 'User not found' }); } console.log('Stored hashed password:', user.password); const passwordMatch = await bcrypt.compare(password, user.password); console.log('Password match:', passwordMatch); if (!passwordMatch) { console.log('Password mismatch'); return res.status(401).json({ message: 'Incorrect password' }); } const secretKey = process.env.SECRET_KEY || 'your-hardcoded-secret-key'; const token = jwt.sign({ userId: user._id }, secretKey, { expiresIn: '1h' }); res.json({ token }); } catch (error) { console.error('Error logging in:', error); res.status(500).json({ message: 'Error logging in' }); } }; module.exports = { register, login };
调试输出
Received login request: { username: 'safiiii', password: 'safi123' } Stored hashed password: $2b$10$yt1UcY4zNZujN1OIYjorQuqPVvDfgfRwV218Biw4gH.k0tbzXk.MK Password match: false Password mismatch Received login request: { username: 'safiiii', password: 'safi123' } Stored hashed password: $2b$10$yt1UcY4zNZujN1OIYjorQuqPVvDfgfRwV218Biw4gH.k0tbzXk.MK Password match: false Password mismatch
1. 密码不匹配的可能原因
- User模型字段配置错误:最常见的是
password字段设置了过短的maxLength,导致bcrypt生成的哈希密码(固定60位左右)被截断;或者模型中存在额外的pre-save钩子,对密码重复执行哈希操作,存储的哈希值并非注册时生成的结果。 - 注册时密码参数异常:虽然注册提示成功,但实际传入
bcrypt.hash的password可能为空或被中间件篡改(比如body解析异常),导致存储的哈希对应空值,自然无法匹配正常密码。 - 数据库数据残留:测试环境中存在之前错误存储的用户数据,新注册的用户被覆盖或读取到旧数据。
2. 修复方案
步骤1:检查并修正User模型
确保password字段为String类型且不限制长度,同时移除任何多余的密码哈希钩子。示例模型代码:
const mongoose = require('mongoose'); const UserSchema = new mongoose.Schema({ username: { type: String, required: true, unique: true }, email: { type: String, required: true, unique: true }, password: { type: String, required: true }, // 不要设置maxLength,bcrypt哈希长度固定 role: { type: String, default: 'student' } }); // 注意:不要添加自动哈希password的pre-save钩子,因为注册时已经手动哈希过 module.exports = mongoose.model('User', UserSchema);
步骤2:验证注册时的密码参数
在注册函数中添加日志,确认传入的原始密码正确:
// 注册函数内添加 console.log('Original password for registration:', password);
步骤3:清理旧数据并重新测试
删除数据库中已存在的测试用户,重新执行注册流程,再尝试登录。
步骤4:排查bcrypt版本兼容性(可选)
虽然Node.js 14.x与bcrypt 5.0.1兼容,但如果上述步骤无效,可以尝试重新安装依赖:
npm uninstall bcrypt && npm install bcrypt@5.0.1
内容的提问来源于stack exchange,提问作者DJABRI MAROUA
相关产品推荐
相关产品推荐

