You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 17:33:00