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

Node.js中bcryptjs compare校验MongoDB密码始终返回false

bcrypt.compare始终返回false问题排查

核心问题原因

  • Schema配置错误:password字段设置了lowercase: true属性,Mongoose写入数据时会自动将字段值转为全小写。而bcrypt生成的哈希值是大小写敏感的,包含大小写混合字符,强制转小写会直接破坏哈希结构,导致比对永远失败。
  • 注册接口逻辑顺序错误:先调用User.create将前端传入的明文密码直接存入数据库,之后才执行bcrypt哈希操作,且后续newUser.save()没有加await,存在时序问题,数据库中存储的根本不是正确生成的哈希值。
  • 登录接口写法不规范:重复查询用户数据、同时混用bcrypt的Promise调用和回调写法、catch块为空不打印错误,既容易产生逻辑bug,也会掩盖实际运行报错。

分步修复方案

1. 修正User Schema配置

删除password字段的lowercase: true配置,避免哈希值被自动转写:

const userSchema = new mongoose.Schema({
    email: {
        type: String,
        required: [true, "Please enter a email"],
        unique: true,
        lowercase: true,
    },
    password: {
        type: String,
        required: [true, "Please enter a password"],
        // 移除lowercase: true配置,禁止自动转换哈希值大小写
    },
});

2. 修正注册接口逻辑

调整执行顺序:先对明文密码做哈希处理,再将哈希值写入数据库,所有异步操作必须加await确保执行完成:

module.exports.signupPost = async (req, res) => {
    const { email, password } = req.body;
    try {
        // 先生成密码哈希
        const hashedPassword = await bcrypt.hash(password, 12);
        // 存储时直接写入哈希值
        const newUser = await User.create({ email, password: hashedPassword });
        res.status(200).json({ user: newUser._id });
    } catch (err) {
        const errors = handlerErr(err);
        res.status(400).json({ errors });
    }
};

3. 修正登录接口逻辑

删除重复的用户查询代码,统一使用bcrypt的Promise写法,补全异常处理逻辑:

module.exports.loginPost = async (req, res) => {
    const { email, password } = req.body;
    try {
        const user = await User.findOne({ email });
        if (!user) {
            return res.status(404).json({ email: "No user found" });
        }
        // 密码比对,不要同时传回调函数和使用await接收结果
        const isMatch = await bcrypt.compare(password, user.password);
        if (isMatch) {
            // 此处编写登录成功后的业务逻辑,比如生成token、返回用户信息
            res.status(200).json({ msg: "Login success" });
        } else {
            return res.status(400).json({ password: "Password is incorrect" });
        }
    } catch (err) {
        console.log("Login error: ", err);
        res.status(500).json({ error: "Internal server error" });
    }
};

修复完成后必须删除之前注册的旧测试用户,重新走注册流程生成新数据。旧数据存储的要么是明文密码、要么是被转成小写的无效哈希,永远无法比对通过。

内容的提问来源于stack exchange,提问作者Dev Dub

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 00:48:24