如何获取当前登录用户并追加至JSON文件?解决req.user未定义问题
解决Express中req.user未定义的问题
首先,你碰到的Cannot read property 'user' of undefined错误,核心原因是请求对象req里没有被正确注入登录用户的信息——简单说就是负责身份验证的中间件没正常工作,导致req压根没有user这个属性。下面一步步帮你排查和解决:
一、先确认你有没有配置身份验证中间件
req.user几乎都是由身份验证中间件(比如Passport.js、express-session配合自定义验证,或者JWT中间件)添加到请求对象里的。如果没配置这类中间件,req自然不会有user属性。
给你列几个常见场景的解决方案:
1. 如果你用的是Passport.js
这是Express生态里最常用的身份验证工具,得先把基础配置做对:
const express = require("express"); const session = require("express-session"); const passport = require("passport"); const LocalStrategy = require("passport-local").Strategy; const app = express(); // 先配置会话中间件——这是Passport存储用户信息的基础 app.use(session({ secret: "your-own-secret-key", // 换成你自己的密钥,别用示例里的 resave: false, saveUninitialized: false })); // 初始化Passport并启用会话支持 app.use(passport.initialize()); app.use(passport.session()); // 配置序列化/反序列化——把用户对象存进会话、从会话取出来 passport.serializeUser((user, done) => { done(null, user.id); // 一般存用户ID就行,不用存整个对象 }); passport.deserializeUser((id, done) => { // 这里写你从数据库/用户存储里根据ID拿用户的逻辑 User.findById(id, (err, user) => { done(err, user); }); }); // 配置本地登录策略(如果用用户名密码登录) passport.use(new LocalStrategy( (username, password, done) => { // 这里写你的用户校验逻辑:查用户、验密码 User.findOne({ username: username }, (err, user) => { if (err) return done(err); if (!user) return done(null, false, { message: "用户名不存在" }); if (!user.checkPassword(password)) return done(null, false, { message: "密码错啦" }); return done(null, user); }); } ));
然后,在需要用req.user的路由上,要么用passport.authenticate()中间件,要么用自定义的验证中间件保护:
// 登录接口 app.post("/login", passport.authenticate("local"), (req, res) => { // 登录成功后,req.user就已经被设置好了 res.redirect("/dashboard"); }); // 需要登录才能访问的路由,用自定义中间件保护 app.get("/dashboard", ensureAuthenticated, (req, res) => { // 这里可以放心用req.user了 console.log(req.user); res.send(`欢迎回来,${req.user.username}`); }); // 自定义的登录校验中间件 function ensureAuthenticated(req, res, next) { if (req.isAuthenticated()) { return next(); } res.redirect("/login"); }
2. 如果你用的是JWT(无会话验证)
这种方式不需要会话,靠请求头里的Token来验证,得自己写中间件解析Token并注入用户信息:
const jwt = require("jsonwebtoken"); // 自定义JWT验证中间件 function authenticateToken(req, res, next) { const authHeader = req.headers["authorization"]; const token = authHeader && authHeader.split(" ")[1]; // Token格式是Bearer <token> if (!token) { return res.sendStatus(401); // 没Token直接返回未授权 } jwt.verify(token, "your-jwt-secret", (err, user) => { if (err) return res.sendStatus(403); // Token无效返回禁止访问 req.user = user; // 把解析后的用户信息挂载到req.user next(); }); } // 在需要验证的接口上用这个中间件 app.post("/append-user", authenticateToken, (req, res) => { // 这里就能正常用req.user了 console.log(req.user); // 接下来写追加到JSON文件的逻辑 const userInfo = req.user; fs.readFile("./target-file.json", "utf8", (err, data) => { if (err) { console.error(err); return res.status(500).send("读取文件失败"); } let jsonContent = JSON.parse(data); jsonContent.loggedUsers.push(userInfo); // 假设你的JSON里有loggedUsers数组 fs.writeFile("./target-file.json", JSON.stringify(jsonContent, null, 2), (err) => { if (err) { console.error(err); return res.status(500).send("写入文件失败"); } res.send("用户信息已成功追加"); }); }); });
二、检查路由的中间件顺序和参数
有时候不是中间件没配置,是顺序错了或者路由函数写法不对:
- 身份验证中间件必须放在需要用
req.user的路由前面,不然路由执行时还没注入用户信息; - 确保你的路由函数是
(req, res, next) => {}的形式,req是第一个参数,别写漏了。
三、调试小技巧
要是还是搞不清问题出在哪,可以在路由里先打印req看看:
app.get("/debug-user", (req, res) => { console.log(req); // 打印整个req对象,看看有没有user属性 if (req.isAuthenticated) { console.log(req.isAuthenticated()); // 用Passport的话,这个方法能判断用户是否登录 } res.send("调试信息已经打印到控制台啦"); });
按照上面的步骤排查,应该就能解决req.user未定义的问题,之后你就能顺利把当前登录用户的信息追加到JSON文件里啦~
内容的提问来源于stack exchange,提问作者Mark White
相关产品推荐
相关产品推荐

