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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 17:01:25