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

MongoDB用户数据更新求助:前端调用接口及Cookie身份验证问题

解决方案

一、后端实现Cookie跟踪登录用户

要通过Cookie识别登录用户,需先配置Cookie解析中间件,再在登录接口设置用户身份Cookie,最后修改/data接口从Cookie获取用户ID。

  1. 安装并引入Cookie解析中间件
npm install cookie-parser

在项目入口文件(如app.js)中添加:

const cookieParser = require('cookie-parser');
app.use(cookieParser());
  1. 修改登录接口,登录成功后设置身份Cookie
    假设你的登录接口逻辑如下,在验证通过后将用户ID写入Cookie:
app.post('/login', async (req, res) => {
  // 用户名密码验证逻辑
  const user = await userCollection.findOne({ username: req.body.username });
  if (user && /* 密码校验通过 */) {
    // 设置HttpOnly Cookie,防止XSS攻击,有效期设为1天
    res.cookie('userId', user._id.toString(), {
      httpOnly: true,
      maxAge: 24 * 60 * 60 * 1000,
      sameSite: 'strict' // 降低CSRF风险
    });
    res.json({ success: true, username: user.username });
  } else {
    res.status(401).json({ message: '登录失败' });
  }
});
  1. 优化/data接口,从Cookie获取用户ID
    不再通过URL参数传递用户ID,直接从Cookie读取:
app.post('/data', async (req, res) => {
  try {
    const { taskCount, coinCount, soldItems } = req.body;
    const userId = req.cookies.userId;

    // 未登录拦截
    if (!userId) {
      return res.status(401).json({ message: "未登录,请先登录" });
    }

    // 若使用原生MongoDB驱动,需将字符串转为ObjectId
    // const { ObjectId } = require('mongodb');
    // const user = await userCollection.findOne({ _id: new ObjectId(userId) });
    
    // 若使用Mongoose,直接传字符串即可自动转换
    const user = await userCollection.findOne({ _id: userId });

    if (!user) {
      return res.status(404).json({ message: "用户不存在" });
    }

    await userCollection.updateOne(
      { _id: userId },
      { $set: { taskCount, coinCount, soldItems } }
    );

    res.json({ taskCount, coinCount, soldItems, username: user.username, userid: user._id });
  } catch (error) {
    console.error("更新数据时出错:", error);
    res.status(500).json({ message: "服务器内部错误" });
  }
});

二、前端调用接口同步数据

从localStorage取出计数数据,通过fetch或axios发送POST请求,注意携带Cookie以验证用户身份。

用fetch实现

// 同步数据到数据库的函数
async function syncUserData() {
  // 从localStorage读取数据,转成数字类型
  const taskCount = parseInt(localStorage.getItem('taskCount')) || 0;
  const coinCount = parseInt(localStorage.getItem('coinCount')) || 0;
  const soldItems = parseInt(localStorage.getItem('soldItems')) || 0;

  try {
    const response = await fetch('/data', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ taskCount, coinCount, soldItems }),
      credentials: 'include' // 携带Cookie
    });

    const result = await response.json();
    if (response.ok) {
      console.log('数据同步成功:', result);
      // 可在此添加用户提示或状态更新逻辑
    } else {
      console.error('数据同步失败:', result.message);
    }
  } catch (error) {
    console.error('请求出错:', error);
  }
}

// 调用时机示例:页面卸载前自动同步
window.addEventListener('beforeunload', syncUserData);
// 或绑定按钮点击事件
// document.getElementById('sync-btn').addEventListener('click', syncUserData);

用axios实现

async function syncUserData() {
  const taskCount = parseInt(localStorage.getItem('taskCount')) || 0;
  const coinCount = parseInt(localStorage.getItem('coinCount')) || 0;
  const soldItems = parseInt(localStorage.getItem('soldItems')) || 0;

  try {
    const response = await axios.post('/data', { taskCount, coinCount, soldItems }, {
      withCredentials: true // 携带Cookie
    });
    console.log('数据同步成功:', response.data);
  } catch (error) {
    console.error('数据同步失败:', error.response?.data?.message || error.message);
  }
}

三、关键注意事项

  • Cookie安全:生产环境建议开启secure: true(仅HTTPS下传输Cookie),进一步提升安全性。
  • 数据类型校验:localStorage存储的是字符串,必须转为数字后再传给后端,避免数据库存入非预期的字符串类型。
  • 错误处理:前端需处理未登录、服务器错误等场景,给用户清晰的反馈提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 05:35:01