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

页面刷新时Express Session丢失导致自动登录失效问题求助

解决Passport.js会话丢失与自动登录失效问题

问题描述

开发前后端分离单页应用,技术栈为Express、React+TypeScript、MongoDB、Passport.js,已实现登录跳转首页,但浏览器刷新后会话丢失,自动登录失效。数据库中会话记录仍存在至过期时间,再次登录会创建新会话。

问题根源分析

  1. Passport中间件顺序错误:Passport初始化与会话中间件被放在路由之后,导致路由处理时无法使用Passport的会话认证功能。
  2. 登录请求未携带Credentials:前端登录请求未配置携带Cookie,浏览器无法保存会话Cookie。
  3. Autologin路由判断逻辑错误:依赖req.session.user判断登录状态,但Passport实际将用户信息存储在req.user中,而非req.session.user。
  4. Session Cookie跨域配置缺失:跨域场景下未设置SameSite属性,浏览器可能阻止Cookie传输。

修复步骤

1. 调整Express中间件顺序

修改index.js,将Passport相关中间件移至路由之前:

const express = require("express");
const cookieParser = require("cookie-parser");
const session = require("express-session")
const MongoStore = require('connect-mongo')
const passport = require('passport')
require('./strategies/local')
const cors = require("cors");

const authRoute = require('./routes/auth');
require('./database')

const app = express();
const PORT = 3001;

app.use(express.json())
app.use(
    cors({
        origin: "http://localhost:5173",
        credentials: true,
    })
);
app.use(express.urlencoded({ extended: true }))
app.use(cookieParser());

// Session配置
app.use(session({
    secret: 'nkjhnjdjjkdhdjwgdzgdwg',
    resave: false,
    saveUninitialized: false, // 避免创建空会话
    store: MongoStore.create({ mongoUrl: 'mongodb://localhost:27017/express-react' }),
    cookie: { 
        maxAge: 20000,
        sameSite: 'none', // 跨域场景必须设置
        secure: process.env.NODE_ENV === 'production', // 生产环境启用HTTPS Cookie
        httpOnly: true // 提升Cookie安全性
    },
}))

// Passport中间件必须在路由之前
app.use(passport.initialize())
app.use(passport.session())

app.use((req, res, next) => {
    console.log(req.method)
    next()
})
app.use(express.static('public'))
app.use('/api/auth', authRoute) // 路由移至Passport中间件之后

app.listen(PORT, () => console.log(`Express Server running on ${PORT}`));

2. 修复前端登录请求Credentials配置

修改Login.tsx的fetch请求,添加credentials: 'include':

const submit = async (ev: FormEvent) => {
    ev.preventDefault();

    const res = await fetch("http://localhost:3001/api/auth/login", {
        method: "POST",
        headers: {
            "Content-Type": "application/json"
        },
        credentials: 'include', // 跨域请求携带Cookie
        body: JSON.stringify({
            "email": (mail_ref.current as HTMLInputElement).value,
            "password": (password_ref.current as HTMLInputElement).value
        })
    });

    if(res.status === 200){
        const data = await res.json(); // 改为json解析
        setLoggedIn(true)
        console.log(data);
    }
};

3. 修正Autologin路由逻辑

修改auth.js的/autologin路由,使用Passport内置方法判断登录状态:

router.get('/autologin', (req, res) => {
    if(req.isAuthenticated()){ // Passport内置的登录状态判断方法
        // 仅返回必要用户信息,避免暴露敏感字段
        const user = { email: req.user.email, id: req.user.id };
        res.status(200).json({loggedIn: true, user})
    } else {
        // 必须返回默认响应,避免前端请求挂起
        res.status(200).json({loggedIn: false})
    }
})

4. 优化登录成功响应

修改auth.js的登录路由,返回用户信息以便前端使用:

router.post('/login', passport.authenticate('local'), (req, res)=>{
    console.log('logged in')
    console.log(req.user) // 确认用户信息已正确序列化
    // 返回用户信息,前端可直接更新状态
    res.status(200).json({ loggedIn: true, user: { email: req.user.email, id: req.user.id }})
})

验证步骤

  1. 重启Express后端服务。
  2. 前端登录后,查看浏览器Application > Cookies是否存在connect.sid Cookie。
  3. 刷新页面,查看/autologin请求返回的loggedIn状态是否为true。
  4. 确认数据库中会话记录未被重复创建。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 20:09:52