Sapper应用中req.user无法设置及获取问题:Express配置排查
让我一步步帮你梳理可能的问题点:
1. 先检查Session Cookie的secure配置
你给session cookie设置了secure: true,这个属性的作用是只有在HTTPS环境下,浏览器才会保存这个cookie。如果你的开发环境是用HTTP(比如localhost),浏览器根本不会存储这个session cookie,登录后session直接丢失,自然拿不到req.user、req.session.user这类值。
解决办法:根据运行环境动态设置secure属性,比如:
cookie: { secure: process.env.NODE_ENV === 'production', maxAge: 604800000 }
2. 确认Passport的序列化/反序列化函数已正确实现
Passport需要你明确告诉它:如何把用户对象序列化到session,以及如何从session里把用户信息反序列化回来。如果没写这两个函数,Passport根本没法把用户信息存进session,也就生成不了req.user。
你需要添加类似这样的代码:
passport.serializeUser((user, done) => { // 通常存用户的唯一标识,比如id done(null, user.id); }); passport.deserializeUser((id, done) => { // 根据id从数据库或存储中获取完整用户对象 User.findById(id, (err, user) => { done(err, user); }); });
3. 检查登录路由的Passport登录流程是否完整
在你的login.js服务端路由里,要确保正确调用了Passport的认证方法,并且在认证成功后完成了用户登录的流程。
比如用Local策略的话,路由代码应该类似:
router.post('/', passport.authenticate('local', { session: true }), (req, res) => { // 认证成功后,req.user应该已经由Passport生成 // 如果需要手动存到req.session.user,可以加这一行 req.session.user = req.user; res.json({ success: true, user: req.user }); });
另外,在Passport策略的回调里,一定要调用done(null, user)来传递用户对象,否则Passport不会把用户信息挂载到req上:
passport.use(new LocalStrategy((username, password, done) => { User.findOne({ username }, (err, user) => { if (err) return done(err); if (!user) return done(null, false); if (!user.verifyPassword(password)) return done(null, false); // 这里必须返回user,Passport才会生成req.user return done(null, user); }); }));
4. 调整Sapper Session中间件的取值逻辑
你当前的Sapper中间件是从req.session.user取用户信息,但Passport默认是把序列化后的用户标识存在req.session.passport.user里,再通过反序列化生成req.user。如果登录流程里没有手动把req.user赋值给req.session.user,那Sapper的session里自然拿不到用户数据。
你可以直接修改Sapper的session函数,用Passport生成的req.user:
sapper.middleware({ session: (req, res) => { return { user: req.user }; } }),
5. 确认中间件的挂载顺序
虽然你的配置里顺序看起来没问题(session → Passport初始化 → Sapper),但要确保你的登录路由是在这些中间件之后挂载的。如果路由挂载在Passport中间件之前,那路由里根本访问不到req.user和session信息。
正确的顺序应该是:
// 先挂载所有基础中间件 app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); app.use(compression({ threshold: 0 })); app.use(sirv('static', { dev })); app.use(cookieParser()); app.use(session(/* ...你的session配置... */)); app.use(passport.initialize()); app.use(passport.session()); // 再挂载登录路由 app.use('/login', require('./routes/login')); // 最后挂载Sapper中间件 app.use(sapper.middleware(/* ...你的Sapper配置... */));
先从这几个方向排查,应该能解决你的问题。
内容的提问来源于stack exchange,提问作者Artur O

