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

Express-session+Passport每次请求创建会话,如何仅登录后生成?

问题:未登录时每次请求都创建新MongoDB会话

我正在开发电商平台前后端,使用Express和Passport实现登录注册系统。当前遇到的问题是:每次访问站点中带请求的页面,都会创建新会话并存入MongoDB,比如浏览3个页面就会生成3条不同的会话记录。我的需求是仅在用户登录后才创建会话。

已经尝试过在Axios请求中启用withCredentials,也设置过saveUninitialized,但都无效。推测是Passport会向Cookie插入空对象,导致会话被标记为已修改,进而触发存储。

原因分析

Passport的passport.session()中间件会在每个请求中尝试反序列化用户。如果用户未登录,req.user会被设为null,这个操作会修改req.session对象(添加passport: {}空字段)。即使设置了saveUninitialized: false,只要会话对象被修改,express-session就会认为会话已初始化,从而将其存入MongoDB。另外原代码中saveUnitialized存在拼写错误,正确应为saveUninitialized,这也导致该配置未生效。

解决方案

核心思路是仅在用户登录成功后才启用Passport会话处理,避免未登录请求触发会话修改和存储。具体步骤如下:

  1. 给Passport会话中间件添加条件判断
    不全局启用passport.session(),而是自定义中间件,仅当会话中已有用户信息时才执行Passport的会话逻辑,未登录请求直接跳过。

  2. 修复saveUninitialized拼写错误
    修正session配置中的拼写错误,确保saveUninitialized: false生效,阻止未初始化的会话被存储。

  3. 调整resave配置(可选)
    将resave设为false,减少不必要的会话存储操作,提升性能。

修改后的关键代码

app.js 核心修改

// 替换原有的app.use(passport.session())
// 自定义中间件:仅已登录用户启用Passport会话处理
app.use((req, res, next) => {
  if (req.session?.user) {
    return passport.session()(req, res, next);
  }
  next();
});

// 修复session配置的拼写错误及优化参数
app.use(session({
    store: MongoStore.create({
        mongoUrl: 'blablabla',
        mongoOptions: {useNewUrlParser: true, useUnifiedTopology: true},
        ttl: 15
    }),
    cookie:{
        maxAge: 7 * 24 * 60 * 60 * 1000,
    },
    secret: 'mysecret',
    resave: false,
    saveUninitialized: false // 修正拼写错误
}))

可选:优化反序列化逻辑

避免未登录时触发不必要的数据库查询:

// passport.config.js 中修改deserializeUser
passport.deserializeUser(async(id, done)=>{
    try {
        const user = await userModel.findById(id);
        done(null, user);
    } catch (err) {
        done(err, null);
    }
})

验证效果

修改完成后,未登录状态下访问页面或接口,MongoDB不会生成新会话记录;只有当用户完成登录或注册操作后,系统才会创建并存储会话,符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 04:02:34