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

Node.js+MongoDB管理员登录报错:邮箱/密码组合无效

管理员登录验证失败:bcrypt比对明文密码导致的问题

问题场景

我在实现管理员登录功能时,MongoDB数据库和.env文件中配置了相同的管理员凭证(邮箱:bkroland19@gmail.com,密码:felinho/013),但调用checkCredentials接口时始终返回“Invalid email/password combination”错误,无法完成登录。

相关代码

const Admin = require('../models/admin');
const Voters = require('../models/voters');
const bcrypt = require('bcrypt');

exports.checkCredentials = async (req, res, next) => {
  const email = req.body.email;
  const password = req.body.password;

  Admin.findOne({ email: email }).exec(async (error, adminData) => {
    if (error) {
      // some error occured
      return res.status(400).json({ error });
    }
    if (adminData) {
      // email is correct checking for password
      const match = await bcrypt.compare(password, adminData.password);
      if (match) {
        req.adminID = adminData._id;
        next();
      } else {
        return res.status(200).json({
          msg: 'Invalid email/password combination yyy',
        });
      }
    } else {
      // no data found for given email
      return res.status(200).json({
        msg: 'Invalid email/password combination !!!!',
      });
    }
  });
};

exports.verifyVoter = async (req, res, next) => {
  let query;
  if (req.query.voterID) {
    query = {
      voterID: req.query.voterID,
    };
  } else {
    query = {
      phone: req.body.phone,
    };
  }
  console.log(query);
  Voters.findOne(query).exec(async (error, voterData) => {
    if (error) {
      // some error occured
      return res.status(400).json({ error });
    }
    if (voterData) {
      // Voter found
      if (voterData.hasRegistered === true) {
        return res.status(200).json({
          msg: 'Voter already registered',
        });
      } else {
        req.phone = voterData.phone;
        req.district = voterData.pinCode;
        req._id = voterData._id;
        next();
      }
    } else {
      // no data found for given Voter
      return res.status(200).json({
        msg: 'Invalid VoterID',
      });
    }
  });
};

.env配置

ADMIN_EMAIL = bkroland19@gmail.com
ADMIN_PASSWORD =felinho/013

MongoDB中的管理员数据

{
    "email": "bkroland19@gmail.com",
    "password": "felinho/013"
}

核心问题

代码中使用bcrypt.compare(password, adminData.password)验证密码,但MongoDB中存储的是明文密码。bcrypt.compare的作用是将输入的明文密码与哈希后的密码进行比对,明文和明文直接比对必然匹配失败,这就是登录报错的根本原因。

修复步骤

  1. 更新MongoDB中的密码为哈希值
    编写临时脚本生成密码的哈希值,替换数据库中的明文密码:

    const bcrypt = require('bcrypt');
    const plainPassword = 'felinho/013';
    bcrypt.hash(plainPassword, 10, (err, hash) => {
      if (err) throw err;
      console.log('哈希后的密码:', hash);
      // 将此哈希值复制到MongoDB的admin文档的password字段中
    });
    
  2. 统一管理员创建逻辑的密码哈希处理
    后续若有创建管理员的接口,必须在保存到数据库前对密码进行哈希:

    const admin = new Admin({
      email: req.body.email,
      password: await bcrypt.hash(req.body.password, 10)
    });
    await admin.save();
    
  3. 优化代码异步处理(可选但推荐)
    代码混合了回调函数与async/await,容易导致嵌套和错误处理混乱,建议统一使用async/await,同时修正状态码规范:

    exports.checkCredentials = async (req, res, next) => {
      try {
        const { email, password } = req.body;
        const adminData = await Admin.findOne({ email });
        
        if (!adminData) {
          return res.status(401).json({ msg: 'Invalid email/password combination' });
        }
        
        const match = await bcrypt.compare(password, adminData.password);
        if (match) {
          req.adminID = adminData._id;
          next();
        } else {
          return res.status(401).json({ msg: 'Invalid email/password combination' });
        }
      } catch (error) {
        return res.status(400).json({ error });
      }
    };
    

    注:验证失败应返回401 Unauthorized状态码,而非200,更符合HTTP规范。

内容的提问来源于stack exchange,提问作者Bukenya KizzaRoland

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 16:01:28