NodeJS登录报错TypeError:无法读取undefined的password属性
问题分析
输入无效邮箱时,数据库查询返回的results是空数组(而非undefined或null),导致你写的!results判断无法触发。代码会继续执行await bcrypt.compare(password, results[0].password),此时results[0]是undefined,读取password属性就会抛出TypeError。另外,db.query回调里的错误不会被外层try/catch捕获,因为这属于异步回调的错误上下文。
修复方案
调整查询结果的判断逻辑,先检查是否存在用户,再做密码比对;同时处理数据库查询的错误:
exports.login = async (req, res) => { try { const { email, password } = req.body; if (!email || !password) { return res.status(400).render('login', { message: 'Please provide an email and password.' }) } db.query('SELECT * FROM users WHERE email = ?', [email], async (error, results) => { // 先处理数据库查询错误 if (error) { console.log(error); return res.status(500).render('login', { message: 'Server error, please try again later.' }) } // 检查是否查询到用户 if (results.length === 0) { return res.status(401).render('login', { message: 'Email or password is incorrect.' }) } // 确认用户存在后再比对密码 const isPasswordMatch = await bcrypt.compare(password, results[0].password); if (!isPasswordMatch) { return res.status(401).render('login', { message: 'Email or password is incorrect.' }) } // 密码正确,生成token并设置cookie const id = results[0].id; const token = jwt.sign({ id }, process.env.JWT_SECRET, { expiresIn: process.env.JWT_EXPIRES_IN }); console.log('The token is: ' + token); const cookieOptions = { expires: new Date( Date.now() + process.env.JWT_COOKIE_EXPIRES * 24 * 60 * 60 * 1000 ), httpOnly: true } res.cookie('jwt', token, cookieOptions); res.status(200).redirect("/"); }) } catch (error) { console.log(error); res.status(500).render('login', { message: 'Server error, please try again later.' }) } }
关键修改点
- 新增
results.length === 0判断:直接捕获邮箱不存在的情况,提前返回错误提示。 - 拆分密码比对逻辑:先确认用户存在,再执行
bcrypt.compare,避免访问undefined的属性。 - 处理
db.query的error:捕获数据库查询异常,避免静默失败。 - 每个分支添加
return:确保响应只发送一次,避免Cannot set headers after they are sent错误。
内容的提问来源于stack exchange,提问作者W3X
相关产品推荐
相关产品推荐

