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

Node.js登录API遇SQL语法错误及Header发送错误,求排查

登录API与认证中间件问题排查

一、当前SQL语法错误原因及修复

  • 直接错误原因:SQL语句中WHERE条件的多个参数用逗号分隔,SQLite不支持这种写法,必须用AND连接条件,这引发了SQLITE_ERROR: near ",": syntax error。
  • 修复后的SQL语句:
    1. 查询用户的SQL:
    SELECT * from user WHERE email = ? AND password = ?
    
    1. 更新token的SQL:
    UPDATE user SET token = ? WHERE email = ? AND password = ?
    

二、潜在逻辑错误(含之前的重复响应问题)

  1. 未验证查询结果有效性:原代码仅处理了查询错误,未判断rows是否为null(即邮箱/密码不匹配的情况),会导致后续错误执行token生成逻辑,甚至触发Can't render headers after they are sent to the client错误。
  2. data.name未定义:返回响应中的data.name从未赋值,会返回undefined,需从查询到的rows中获取真实用户名。
  3. UPDATE操作未处理异常:db_mariposa.run缺少错误回调,无法捕获更新token时的异常。
  4. 密码重复加密:更新token时再次对data.password做MD5加密,但data.password已经是加密后的结果,重复加密会导致条件匹配失败。

修复后的登录路由代码:

users_router.post("/login", (req, res, next) => {
    const data = {
        email: req.body.email,
        password: req.body.password ? md5(req.body.password) : null
    };

    const sql_retrieve = "SELECT * from user WHERE email = ? AND password = ?";
    const params = [data.email, data.password];

    db_mariposa.get(sql_retrieve, params, (err, rows) => {
        if (err) {
            return res.status(400).json({"error": err.message});
        }
        // 新增:校验用户是否存在
        if (!rows) {
            return res.status(401).json({"error": "邮箱或密码错误"});
        }

        const token = jwt.sign(
            { user_email: data.email },
            "secret",
            { expiresIn: "2h" }
        );

        const sql_update = "UPDATE user SET token = ? WHERE email = ? AND password = ?";
        db_mariposa.run(sql_update, [token, data.email, data.password], (updateErr) => {
            if (updateErr) {
                return res.status(500).json({"error": updateErr.message});
            }
            return res.status(200).json({
                "my_token": token, 
                "name": rows.name, 
                "email": rows.email
            });
        });
    });
});

三、认证中间件的逻辑问题

  • 问题:req.user_email = decoded;中,decoded是JWT解析后的完整对象(包含user_email、过期时间等字段),后续使用req.user_email时会拿到整个对象,而非预期的邮箱字符串。
  • 修复:只赋值邮箱字段:
const verifyToken = (req, res, next) => {
    const token = req.headers["my_token"];

    if (!token) {
        return res.status(403).send("A token is required for authentication");
    }

    try {
        const decoded = jwt.verify(token, 'secret');
        req.user_email = decoded.user_email;
        console.log("Valid token!");
    } catch (err) {
        return res.status(401).send("Invalid Token");
    }

    return next();
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 07:54:58