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

Passport serializeUser报Cannot set properties of undefined错误

问题背景

在Express项目中配置Passport.js实现本地账号密码认证,核心实现代码如下:

app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(session({
  secret: "secret_shh",
  resave: true,
  saveUninitialized: true,
}));

app.use(passport.initialize());
app.use(passport.session());

passport.use(new PASSPORT_LOCAL_STRATEGY(
  (username, password, done) => {
    if (username === "test" && password === "passwrd") {
      return done(null, {username: username});
    } else {
      return done(null, false);
    }
  }
));

passport.serializeUser((user, done) => {
  done(null, user.username);
});

passport.deserializeUser((username, done) => {
  done(null, {username: username})
}); 

router.post('/login', 
  passport.authenticate('local', {
    failureRedirect: '/failure',
    successRedirect: '/success'
  }
));

测试接口时出现固定现象:提交错误用户名密码时,服务可正常跳转至failureRedirect配置的失败路由;提交正确用户名密码时,抛出serializeUser执行错误:Passport fail to serializeUser. TypeError: Cannot set properties of undefined (setting: 'user')。

错误诱因

该错误的核心原因是Express中间件挂载顺序错误:

  • 认证失败场景下,Passport不会执行Session写入操作,直接跳转失败路由,因此可以正常响应
  • 认证成功场景下,Passport需要将用户标识写入req.session.passport.user字段完成登录态持久化,如果包含/login路由的路由模块被挂载在express-session、passport.session()中间件之前,请求到达路由逻辑时还未经过Session中间件处理,req对象上不存在session属性,给undefined设置user属性就会抛出上述类型错误。
修复方案

严格按照以下顺序调整中间件和路由的挂载逻辑,顺序不可颠倒:

  1. 优先挂载请求体解析中间件:express.json()、express.urlencoded()
  2. 其次挂载Session中间件:express-session的实例
  3. 再挂载Passport相关中间件:passport.initialize()、passport.session()
  4. 最后挂载所有业务路由模块

调整后的正确挂载示例:

const express = require('express');
const session = require('express-session');
const passport = require('passport');
// 按项目实际引入方式配置本地策略即可
const PASSPORT_LOCAL_STRATEGY = require('passport-local').Strategy;
const router = require('./your-router-path'); // 替换为实际路由文件路径
const app = express();

// 1. 挂载请求体解析中间件
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// 2. 挂载Session中间件
app.use(session({
  secret: "secret_shh",
  resave: false, // 生产环境建议设为false,避免无修改时重复写入session
  saveUninitialized: false, // 生产环境建议设为false,符合隐私合规要求
}));

// 3. 挂载Passport中间件
app.use(passport.initialize());
app.use(passport.session());

// 原有Passport策略、序列化/反序列化逻辑无需修改
passport.use(new PASSPORT_LOCAL_STRATEGY(
  (username, password, done) => {
    if (username === "test" && password === "passwrd") {
      return done(null, {username: username});
    } else {
      return done(null, false);
    }
  }
));

passport.serializeUser((user, done) => {
  done(null, user.username);
});

passport.deserializeUser((username, done) => {
  done(null, {username: username})
});

// 4. 最后挂载业务路由
app.use(router);

app.listen(3000);

额外检查项:

  • 确认已通过npm i express-session正确安装Session依赖,且引入的session变量无拼写错误
  • 原有/login路由的Passport认证配置无需修改,顺序调整后即可正常工作

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 00:09:21