Node.js认证中间件中如何将用户数据传递至后续路由处理函数?
Node.js认证中间件中如何将用户数据传递至后续路由处理函数?
Hey there! Let's break down why your currentUser was coming up undefined and how to properly pass user data to your buyCourse handler.
问题出在哪?
你最初的代码里,数据库查询是放在db.getConnection和connection.query的回调函数里的——这俩都是异步操作!但你后面判断!currentUser、给req.user赋值的代码是同步执行的,也就是说,当代码走到这些逻辑的时候,数据库查询还没跑完呢,currentUser自然就是undefined啦。
你修改后的代码方向是对的,但可以更优雅
你改用了jwt.verify的回调,把数据库查询嵌套进去,这确实解决了异步顺序的问题,但回调嵌套多了容易变成“回调地狱”,维护起来麻烦。咱们可以用async/await把异步代码改得更清晰,同时也能确保每一步都执行完再走下一步。
优化后的完整代码示例
先把数据库操作改成Promise形式(用Node.js自带的util.promisify包装),这样就能用async/await了:
const util = require('util'); const jwt = require('jsonwebtoken'); const mysql = require('mysql'); // 假设你的db是已经配置好的数据库连接池 // 把回调式的方法转成Promise形式 const getConnection = util.promisify(db.getConnection).bind(db); exports.protect = async (req, res, next) => { try { // 1) 获取并校验token是否存在 let token; if (req.headers.authorization && req.headers.authorization.startsWith("Bearer")) { token = req.headers.authorization.split(" ")[1]; } else if (req.cookies.jwt) { token = req.cookies.jwt; } if (!token) { return res.status(401).json({ status: "fail", message: "You are not logged in. Please login to get access", }); } // 2) 验证token有效性 const decoded = jwt.verify(token, process.env.JWT_SECRET); if (!decoded) { return res.status(403).json({ status: "fail", message: "Token invalid" }); } // 3) 检查用户是否仍存在于数据库 const connection = await getConnection(); // 把query方法也转成Promise形式,绑定当前连接 const query = util.promisify(connection.query).bind(connection); const sqlSearch = "SELECT * FROM users WHERE id = ?"; const searchQuery = mysql.format(sqlSearch, [decoded.id]); // 查询结果是数组,取第一个元素(因为用户id唯一) const [currentUser] = await query(searchQuery); connection.release(); // 释放数据库连接 if (!currentUser) { return res.status(401).json({ status: "fail", message: "The user belonging to this token no longer exists", }); } // 关键一步:把用户数据挂载到req对象上 req.user = currentUser; res.locals.user = currentUser; next(); // 调用下一个中间件/路由处理函数 } catch (err) { // 统一处理错误 res.status(500).json({ status: "error", message: err.message }); } };
后续路由处理函数怎么用?
在你的buyCourse函数里,直接通过req.user就能拿到用户数据了:
exports.buyCourse = async (req, res) => { // 获取当前登录用户 const loggedInUser = req.user; console.log("正在购买课程的用户:", loggedInUser); // 这里写你的课程购买逻辑,比如校验用户余额、生成订单等 // ... res.status(200).json({ status: "success", message: "Course purchased successfully", data: { /* 订单数据等 */ } }); };
小提示
- 一定要记得在异步操作出错的时候处理错误,用
try/catch包裹是个好习惯; - 数据库连接用完要记得释放,避免连接池耗尽;
- 用
mysql.format来拼接SQL语句,能防止SQL注入哦~
备注:内容来源于stack exchange,提问作者Szymon Tymuła
相关产品推荐
相关产品推荐

