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

Express中Session读取异常求助:MongoStore存储后获取为undefined

问题:Express Session 在跨域请求中无法读取(MongoDB Atlas已存储但req.session为undefined)

我正在开发一个React应用,使用Express作为后端,通过MongoStore存储Session数据。登录MongoDB Atlas后可以看到Session已创建且变量已存储,但尝试访问Session时却得到undefined。

后端Express代码

const express = require('express');
const cors = require('cors');
const session = require('express-session');

const mongoose = require('mongoose');
const MongoDBStore = require('connect-mongodb-session')(session);
const MONGODB_URI = "MY MONGODB ATLAS URL";
const store = new MongoDBStore({
    uri: MONGODB_URI,
    collection: 'sessions'
});

const app = express();
const port = process.env.PORT || 3001;

app.use(cors());
app.use(session({
    secret: 'mysecretkey',
    resave: false,
    saveUninitialized: false,
    store: store
}));
app.use(express.json());

app.get('/csrf', (req, res) => {
    if(req.headers['sec-fetch-site'] === 'same-site'){
        const csrf = 'ABCDEFG';
        req.session.csrf = csrf;
        req.session.save(err => {
            if (err) {
                console.log('Session save error:', err);
                return res.status(500).json({ error: 'Session save error' });
            }
            console.log('CSRF Token set:', csrf);
            res.json({ csrf: csrf });
        });
    }else{
        res.status(403).json({ error: 'Invaid Entry' })
    }
});

app.get('/test-get', (req, res) => {
    res.json({ message: req.session })
})

app.post('/login', (req, res) => {
    if(req.headers['sec-fetch-site'] === 'same-site'){
        console.log('Session data on /login:', req.session);
        console.log('CSRF Token on /login:', req.session.csrf);
        if (req.session.csrf) {
            res.json({ message: 'Login successful', csrf: req.session.csrf });
        } else {
            res.status(400).json({ error: 'CSRF token missing' });
        }
    }else{
        res.status(403).json({ error: 'Invaid Entry' })
    }
})

mongoose
    .connect(MONGODB_URI)
    .then(result => {
        app.listen(port, () => {
            console.log(`Server running on port ${port}`);
        });
    })
    .catch(err => {
        console.log(err);
});

前端React代码

获取CSRF Token

const[csrf, setCSRF] = useState('');

useEffect(() => {
    fetch(PROCESSURL + 'csrf', { method: 'GET' })
        .then((res) => res.json())
        .then((data) => {
            setCSRF(data.csrf);
        })
        .catch(() => {
            alert('Server: 403');
        })
}, []);

登录提交

const handleSubmit = (event) => {
    event.preventDefault();
    formData['csrf'] = csrf;
    fetch(PROCESSURL + 'login', { 
        method: "POST",
        headers: {
            'Content-Type': 'application/json',
            csrf: csrf
        },
        body: JSON.stringify(formData)
    })
        .then((res) => res.json())
        .then((data) => {
            alert(data);
        })
}

解决方案

问题核心是跨域请求中Session Cookie未被正确传递,导致后端无法识别当前请求对应的Session。以下是具体修改步骤:

1. 修正CORS配置

默认cors()不允许携带凭证(Cookie),需明确配置允许凭证并指定前端Origin:

// 替换原app.use(cors());
app.use(cors({
  origin: 'http://localhost:3000', // 替换为你的React前端实际地址
  credentials: true // 允许携带Cookie
}));

2. 完善Session的Cookie配置

跨域场景下需明确Cookie的SameSite和Secure属性,确保浏览器允许传递:

// 替换原session配置
app.use(session({
    secret: 'mysecretkey',
    resave: false,
    saveUninitialized: false,
    store: store,
    cookie: {
        httpOnly: true, // 增强安全性,防止前端JS读取Cookie
        sameSite: process.env.NODE_ENV === 'production' ? 'none' : 'lax', // 生产环境HTTPS下用none,开发环境用lax
        secure: process.env.NODE_ENV === 'production' // 生产环境开启HTTPS时设为true
    }
}));

3. 前端Fetch请求添加凭证参数

两段Fetch请求都需要加上credentials: 'include',确保Cookie被发送到后端:

获取CSRF的修改:

useEffect(() => {
  fetch(PROCESSURL + 'csrf', { 
    method: 'GET',
    credentials: 'include' // 添加此行
  })
  .then((res) => res.json())
  .then((data) => {
    setCSRF(data.csrf);
  })
  .catch(() => {
    alert('Server: 403');
  })
}, []);

登录请求的修改:

const handleSubmit = (event) => {
  event.preventDefault();
  formData['csrf'] = csrf;
  fetch(PROCESSURL + 'login', { 
    method: "POST",
    headers: {
      'Content-Type': 'application/json',
      csrf: csrf
    },
    credentials: 'include', // 添加此行
    body: JSON.stringify(formData)
  })
  .then((res) => res.json())
  .then((data) => {
    alert(JSON.stringify(data)); // 建议转成字符串,否则alert会显示[object Object]
  })
}

关键原因说明

跨域请求时,浏览器默认会阻止Cookie的传递。只有当后端CORS配置允许凭证、前端请求明确携带凭证,且Cookie的SameSite/Secure属性符合浏览器安全规则时,Session Cookie才能被正确发送到后端,后端才能通过Cookie找到对应的Session数据(即使Atlas中已有存储,没有Cookie也无法关联到当前请求)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 00:40:57