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

使用Expressjs实现多用户同时登录时独立展示对应发票咨询

问题根因

你用app.set()存储的Users和userInvoices是Express应用实例的全局属性,所有用户的请求共享该实例,因此后登录的用户会拿到前一个用户存入全局的数据,这是多用户串数据的核心原因。

1. express-session可以解决该问题

session是基于用户独立存储的服务端数据,每个用户对应唯一的会话标识,不会出现跨用户数据串用的问题。

具体实现步骤

第一步 安装依赖

npm install express-session connect-mongo

用connect-mongo将会话数据存在MongoDB中,适配你的技术栈,避免内存存储会话在生产环境丢失数据、无法多实例部署的问题。

第二步 配置会话中间件

在Express项目的入口文件(如app.js)中,路由注册前添加如下配置:

const session = require('express-session');
const MongoStore = require('connect-mongo');

app.use(session({
  secret: process.env.SESSION_SECRET, // 加密密钥存在环境变量中,不要明文写在代码里
  resave: false,
  saveUninitialized: false,
  store: MongoStore.create({ mongoUrl: process.env.MONGO_URI }), // 替换为你的MongoDB连接串
  cookie: {
    maxAge: 7 * 24 * 60 * 60 * 1000, // 会话有效期7天
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production' // 生产环境开启HTTPS后设为true
  }
}));

第三步 改造现有业务代码

将所有全局app.set/app.get的调用改为基于req.session的用户级存储,同时优化冗余逻辑:

  1. 改造/saveUser接口:
userInvoices.post('/saveUser', async (req, res) => {
  try {
    const User = req.body;
    const usersFromDB = await fetchUsersFromDB();
    findCommonUser(usersFromDB, User);
    // 把用户信息存在当前用户的会话中,不是全局
    req.session.user = User;
    res.status(200).json({msg: '用户信息保存成功'});
  } catch (error) {
    console.log(error);
    res.status(500).json({msg: '保存失败'});
  }
})
  1. 改造发票匹配逻辑,删除全局存储:
// 直接返回筛选后的发票数组,不需要存入全局
function matchUserAndInvoice(dbInvoices, loggedInUser) {
  return dbInvoices.filter(DBElement => DBElement.customer_email === loggedInUser.email);
}
  1. 改造/fetchUserInvoices接口:
userInvoices.get('/fetchUserInvoices', async (req,res) => {
  try {
    // 先校验用户登录状态
    if(!req.session.user) {
      return res.status(401).json({msg: '未登录'});
    }
    // 优化:直接在数据库查询时过滤对应用户的发票,不用查全表再过滤,性能更高
    const userInvoices = await InvoiceModel.find({customer_email: req.session.user.email});
    res.json(userInvoices);
  } catch (error) {
    console.log(error);
    res.status(500).json({msg: '查询失败'});
  }
});
2. 更优的解决方案:JWT校验

你已经用了Auth0做认证,JWT(JSON Web Token)方案更适配前后端分离的MERN栈,比session方案更适合生产环境:

  • 前端登录Auth0后会拿到JWT令牌,每次请求接口时放在请求头Authorization: Bearer <你的JWT令牌>中
  • 后端添加Auth0的JWT校验中间件,自动校验令牌合法性,解析出用户信息存在req.user中
  • 不需要服务端存储会话,服务端无状态,更容易做分布式部署,也不会出现会话过期、存储同步的问题
  • 后续查询发票直接用req.user.email作为过滤条件查询数据库即可,完全不会出现用户数据串用的问题。
现有代码其他可优化点
  • matchUserAndInvoice中使用forEach包裹异步逻辑的写法有问题,异步任务不会等待执行完成,容易返回空数组
  • saveUser中使用updateMany没必要,用户邮箱是唯一标识,用updateOne即可
  • 全局调用的clientCall()无实际作用,可以直接删除

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 18:06:02