Express中间件next()失效:已登录用户仍被重定向至登录页
嘿,我刚仔细捋了你的问题,咱们一步步来排查这个让你困惑的问题哈!
首先,你的核心问题是已登录用户触发isLoggedIn中间件时,本该执行next()进入后续的res.render,结果却被重定向到登录页,这大概率是因为req.isAuthenticated()没有返回预期的true,或者中间件/路由配置有细节疏漏。咱们从最可能的原因开始排查:
1. 先检查Passport的Session配置是否完整
req.isAuthenticated()完全依赖Passport的Session支持,如果这部分配置错了,不管用户有没有登录,这个方法都会返回false。你得确认这几点:
- 有没有正确配置
express-session(要放在Passport初始化之前):
// 示例配置,替换成你的密钥和参数 app.use(session({ secret: 'your-custom-secret-key', resave: false, saveUninitialized: false, // 如果用MongoDB存session,还要加store配置,比如connect-mongo }));
- 有没有在Session之后初始化Passport并启用Session:
app.use(passport.initialize()); app.use(passport.session()); // 这一步很关键,没加的话Passport无法维护用户登录状态
- 有没有实现Passport的序列化/反序列化函数:
passport.serializeUser((user, done) => { done(null, user.id); // 把用户ID存在session里 }); passport.deserializeUser((id, done) => { // 从数据库里通过ID找到用户,挂载到req.user上 User.findById(id, (err, user) => { done(err, user); }); });
2. 修复中间件和登录路由的Session变量名不一致问题
你在isLoggedIn中间件里存的是req.session.redirectTo,但登录路由里取的是req.session.returnTo——这俩变量名不统一!虽然这不是导致已登录用户被重定向的直接原因,但会导致登录后的重定向逻辑失效,顺便一起改掉:
// 修改isLoggedIn中间件的变量名 function isLoggedIn(req, res, next) { console.log("当前用户登录状态:", req.isAuthenticated()); // 加个日志,方便排查 console.log("当前用户信息:", req.user); if(req.isAuthenticated()) { return next(); } req.session.returnTo = req.originalUrl; // 和登录路由统一 res.redirect("/login"); }
3. 验证Local策略的登录逻辑是否正确
如果你的Passport Local策略在验证用户时,没有正确调用done(null, user)(比如密码验证失败时返回了done(null, false)),用户根本不会被标记为登录状态。检查你的Local策略代码:
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: '用户名错误' }); // 用bcrypt验证密码(假设你存的是加密后的密码) bcrypt.compare(password, user.password, (err, isMatch) => { if (err) return done(err); if (isMatch) { return done(null, user); // 这里必须返回user,Passport才会标记用户为登录 } else { return done(null, false, { message: '密码错误' }); } }); }); }));
4. 确认路由中间件的顺序是否正确
确保isLoggedIn中间件是放在你要保护的路由前面的,比如:
// 正确顺序:先挂载中间件,再定义路由 app.get("/albums/new", isLoggedIn, (req, res) => { res.render("albums/new"); // 已登录用户会走到这里 });
如果中间件放在路由之后,它根本不会被执行,但你的情况是被重定向,所以这个概率较低,但还是要确认。
最后一步:加日志排查
在isLoggedIn中间件里加我刚才写的日志,启动服务后,登录用户再点击“添加新专辑”,看控制台输出的req.isAuthenticated()是true还是false:
- 如果是
false:回到步骤1和3,检查Passport的Session配置和登录策略; - 如果是
true:那可能是后续路由的问题,比如你定义的/albums/new路由有其他逻辑导致重定向?
内容的提问来源于stack exchange,提问作者Shaurya Dey

