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属性就会抛出上述类型错误。
修复方案
严格按照以下顺序调整中间件和路由的挂载逻辑,顺序不可颠倒:
- 优先挂载请求体解析中间件:
express.json()、express.urlencoded() - 其次挂载Session中间件:
express-session的实例 - 再挂载Passport相关中间件:
passport.initialize()、passport.session() - 最后挂载所有业务路由模块
调整后的正确挂载示例:
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
相关产品推荐
相关产品推荐

