You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 05:13:16