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的作用是将输入的明文密码与哈希后的密码进行比对,明文和明文直接比对必然匹配失败,这就是登录报错的根本原因。
修复步骤
更新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字段中 });统一管理员创建逻辑的密码哈希处理
后续若有创建管理员的接口,必须在保存到数据库前对密码进行哈希:const admin = new Admin({ email: req.body.email, password: await bcrypt.hash(req.body.password, 10) }); await admin.save();优化代码异步处理(可选但推荐)
代码混合了回调函数与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
相关产品推荐
相关产品推荐

