Node.js登录API遇SQL语法错误及Header发送错误,求排查
登录API与认证中间件问题排查
一、当前SQL语法错误原因及修复
- 直接错误原因:SQL语句中WHERE条件的多个参数用逗号分隔,SQLite不支持这种写法,必须用
AND连接条件,这引发了SQLITE_ERROR: near ",": syntax error。 - 修复后的SQL语句:
- 查询用户的SQL:
SELECT * from user WHERE email = ? AND password = ?- 更新token的SQL:
UPDATE user SET token = ? WHERE email = ? AND password = ?
二、潜在逻辑错误(含之前的重复响应问题)
- 未验证查询结果有效性:原代码仅处理了查询错误,未判断
rows是否为null(即邮箱/密码不匹配的情况),会导致后续错误执行token生成逻辑,甚至触发Can't render headers after they are sent to the client错误。 - data.name未定义:返回响应中的
data.name从未赋值,会返回undefined,需从查询到的rows中获取真实用户名。 - UPDATE操作未处理异常:
db_mariposa.run缺少错误回调,无法捕获更新token时的异常。 - 密码重复加密:更新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
相关产品推荐
相关产品推荐

