passport.js LocalStrategy AJAX登录认证无法建立会话问题求助
问题描述
尝试使用passport.js实现AJAX登录功能,采用express-session作为会话存储,该存储方式在OIDC等其他策略下可正常工作。
配置代码
export function configure(passport) { passport.serializeUser(function (user, done) { done(null, user); }); passport.deserializeUser(function (user, done) { done(null, user); }); passport.use( new LocalStrategy( { usernameField: "email", passwordField: "password", }, async (email, password, done) => { try { const response = await postAPI( "auth/authenticate", { email, password }, null, null, true ); if (response.ok) { // got authenticated user return done(null, response.data); } else { return done(null, false, { message: "Invalid login credentials", }); } } catch (err) { return done(null, false, { message: "Login failed", }); } } ) ); }
登录路由代码
router.post("/login", (req, res, next) => { passport.authenticate("local", (err, user, info) => { if (err || !user) { return res.status(401).json({ info }); } else { return res.status(200).json({ user }); } })(req, res, next); });
当前认证成功或失败时均能向客户端返回正确响应,但认证成功后未建立会话,req.session中无passport对象,isAuthenticated()校验判定为未认证,导致用户被重定向至登录页。请问缺少了什么配置?
解决方案
问题出在使用自定义回调函数调用passport.authenticate时,Passport不会自动创建会话,必须手动调用req.login()方法完成会话建立。
修改登录路由代码,在认证成功后添加req.login()逻辑:
router.post("/login", (req, res, next) => { passport.authenticate("local", (err, user, info) => { if (err || !user) { return res.status(401).json({ info }); } // 手动调用req.login序列化用户并建立会话 req.login(user, (loginErr) => { if (loginErr) { return next(loginErr); } return res.status(200).json({ user }); }); })(req, res, next); });
关键说明
- 当不使用自定义回调时,Passport会自动执行
req.login()创建会话;但自定义回调会覆盖这一默认行为,因此需要手动触发。 req.login()会调用passport.serializeUser,将用户信息存入req.session.passport,后续请求就能通过isAuthenticated()校验用户身份。
内容的提问来源于stack exchange,提问作者PJD
相关产品推荐
相关产品推荐

