MEAN栈中bcrypt.compareSync验证密码报错:非法参数undefined, string
解决bcrypt.compareSync抛出"Illegal arguments: undefined, string"错误
错误根源
从报错信息可以直接定位问题:bcrypt.compareSync函数的第一个参数(明文密码)是undefined,第二个参数(数据库存储的哈希密码)是正常字符串,导致函数抛出非法参数错误。
可能原因
- 后端未配置请求体解析中间件,导致
req.body为空,无法获取前端传递的password字段 - 前端请求时未正确传递
password字段,或字段名拼写错误(比如写成pwd、passwd) - 登录接口未提前校验
req.body.password是否存在,直接传入bcrypt函数引发报错
解决方案
1. 确保Express配置了请求体解析中间件
在你的Express主入口文件(如app.js/server.js)中添加以下代码,解析JSON格式的请求体:
const express = require('express'); const app = express(); // 解析JSON请求体(必须添加) app.use(express.json()); // 如果前端使用form-data或x-www-form-urlencoded格式,补充以下配置 app.use(express.urlencoded({ extended: true })); // 挂载用户路由 const userRouter = require('./routes/user'); app.use('/api/users', userRouter);
2. 修复登录接口的参数校验逻辑
在登录接口中先校验password字段是否存在,避免直接传入bcrypt引发错误:
router.post("/login", async (req, res) => { // 先校验邮箱和密码是否存在 if (!req.body.email || !req.body.password) { return res.status(400).send("请提供邮箱和密码"); } const user = await User.findOne({ email: req.body.email }); if (!user) { return res.status(400).send("用户不存在"); } // 安全调用密码比对 const isPasswordValid = bcrypt.compareSync(req.body.password, user.passwordHash); if (isPasswordValid) { res.status(200).send("用户认证成功"); } else { res.status(400).send("密码错误"); } });
3. 修复用户创建接口的哈希逻辑(额外问题)
你的用户创建接口中存在逻辑错误:用req.body.passwordHash进行哈希,这会导致前端传的明文密码无法正确存储。应该改为用req.body.password生成哈希:
router.post("/", async (req, res) => { if (!req.body.password) { return res.status(400).send("请设置密码"); } let user = new User({ name: req.body.name, email: req.body.email, color: req.body.color, // 用前端传递的明文密码生成哈希 passwordHash: bcrypt.hashSync(req.body.password, 10), phone: req.body.phone, isAdmin: req.body.isAdmin, apartment: req.body.apartment, zip: req.body.zip, city: req.body.city, country: req.body.country, }); user = await user.save(); if (!user) return res.status(400).send("用户创建失败"); // 返回用户信息时隐藏密码哈希 res.send(await User.findById(user._id).select("-passwordHash")); });
内容的提问来源于stack exchange,提问作者Niall Caffrey
相关产品推荐
相关产品推荐

