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

Passport JS req.user返回undefined及serializeUser提示id属性不存在问题

问题根因与解决方案

1. VS Code类型报错(user不存在id属性)的原因

这个是Mongoose类型定义/虚拟属性配置问题,运行时能拿到user.id是因为Mongoose默认会给文档生成虚拟属性id,值为_id的字符串格式,只是类型定义没有识别到,不属于运行时报错,不影响代码执行。

2. req.user为undefined的核心原因

你当前的session输出中仅包含cookie字段,没有passport属性,说明用户登录后没有成功触发passport的序列化流程,核心问题出在两处:

  • verifyCallback的Promise链断裂:你在User.findOne的回调中调用bcrypt.compare时没有返回对应的Promise,导致passport无法接收校验完成后返回的user对象,不会触发后续的serializeUser逻辑。
  • 可能存在路由顺序/登录逻辑配置问题:如果登录路由定义在app.use(passport.session())之前,或者自定义passport回调时没有手动调用req.login(),也会导致序列化不生效。

修复步骤

步骤1:修复verifyCallback的Promise返回

修改passport.js中的verifyCallback代码,给bcrypt.compare添加return:

const verifyCallback = (username, password, done) => {
  User.findOne({ username: username })
    .then((user) => {
      if (!user) {
        return done(null, false);
      }
      // 新增return,将bcrypt的校验Promise返回给上层
      return bcrypt.compare(password, user.password).then((isMatch) => {
        if (isMatch) {
          return done(null, user);
        } else {
          return done(null, false);
        }
      });
    })
    .catch((err) => {
      done(err);
    });
};

步骤2:检查登录路由配置

确保登录路由定义在app.use(passport.session())之后,并且正确调用认证逻辑:
如果用默认的passport.authenticate中间件:

// 必须放在passport.session()中间件之后
app.post('/login', passport.authenticate('local'), (req, res) => {
  res.json({ status: 'success', user: req.user });
});

如果用自定义回调写法,必须手动调用req.login()触发序列化:

app.post('/login', (req, res, next) => {
  passport.authenticate('local', (err, user, info) => {
    if (err) return next(err);
    if (!user) return res.json({ status: 'fail', msg: '用户名或密码错误' });
    // 手动调用login触发序列化流程
    req.logIn(user, (err) => {
      if (err) return next(err);
      return res.json({ status: 'success', user: req.user });
    });
  })(req, res, next);
});

步骤3:修复VS Code类型提示问题

在你的User Schema配置中显式开启id虚拟属性:

const userSchema = new mongoose.Schema({
  username: String,
  password: String,
  // 其他字段
}, {
  id: true, // 显式开启id虚拟属性,解决类型提示问题
  timestamps: true
});

如果是纯JS项目,可以在serializeUser那行上方添加// @ts-ignore临时忽略类型提示即可。

验证修复效果

登录成功后,控制台打印的session会新增passport字段,格式如下:

{
  cookie: { /* 原有cookie配置 */ },
  passport: {
    user: '6186c13beb18d33d5088f7b2'
  }
}

此时req.user会被deserializeUser正确赋值,不再返回undefined。

内容的提问来源于stack exchange,提问作者Tayne

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 06:27:00