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

Node.js Web应用/login页面泄露数据库所有用户数据的问题求助

紧急修复数据泄露问题

1. 立即移除危险的GET路由

你的app.get('/login')路由会无差别返回所有用户的完整数据(包括明文密码),这是核心泄露点。直接删除该路由,如果确实需要查看用户数据,必须做严格的权限控制(见下文)。

2. 修复POST登录接口的安全问题

当前POST接口存在两个严重问题:明文存储密码、返回敏感用户数据。修改方案如下:

  • 禁止明文存储密码:使用哈希算法(如bcrypt)加密密码后再存入数据库。
  • 不返回敏感数据:登录验证成功后只返回必要信息(如登录状态、用户名),绝不返回密码。
  • 修正逻辑:当前逻辑会自动注册不存在的用户,这不符合常规登录流程,建议拆分出单独的/register注册接口。
路由访问安全保障措施
  • 身份验证:对敏感路由(如用户信息、后台接口)使用JWT(JSON Web Token)验证。用户登录成功后发放token,后续请求需在请求头携带token,服务器验证token合法性后才允许访问。
  • 权限分级:区分普通用户和管理员权限,仅管理员能访问用户列表等敏感接口,普通用户仅能查看自己的信息。
  • 密码安全规范:
    • 使用bcrypt等慢哈希算法加密密码,避免使用MD5、SHA1等易破解的算法。
    • 登录时,将用户输入的密码哈希后与数据库中的哈希值对比,而非直接比较明文。
  • 输入校验:对用户输入的用户名、密码进行格式、长度校验,防止恶意输入。
  • 强制HTTPS:部署应用时启用HTTPS,防止数据在传输过程中被窃听或篡改。
  • 错误信息脱敏:不要将数据库错误、服务器内部细节返回给前端,统一返回友好的通用错误提示,避免泄露系统信息。
修正后的代码示例

首先安装依赖:

npm install bcrypt

修改后的核心代码:

const bcrypt = require('bcrypt');
const saltRounds = 10; // 哈希迭代次数,值越高越安全,性能消耗也越大

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// 登录接口
app.post('/login', async (req, res) => {
  try {
    const { username, password } = req.body;

    // 校验输入完整性
    if (!username || !password) {
      return res.status(400).send({ message: '用户名和密码不能为空' });
    }

    // 查询用户(用户名应保证唯一,用findOne而非find)
    const user = await dbo.collection("data").findOne({ username });
    if (!user) {
      return res.status(401).send({ message: '用户名或密码错误' });
    }

    // 验证密码哈希
    const isPasswordValid = await bcrypt.compare(password, user.password);
    if (!isPasswordValid) {
      return res.status(401).send({ message: '用户名或密码错误' });
    }

    // 这里可添加JWT生成逻辑,示例:
    // const token = jwt.sign({ userId: user._id, username: user.username }, '你的密钥', { expiresIn: '1h' });
    // res.send({ message: '登录成功', token, username: user.username });

    // 临时返回基础成功信息
    res.send({ message: '登录成功', username: user.username });
  } catch (err) {
    console.error(err);
    res.status(500).send({ message: '服务器内部错误' });
  }
});

// 注册接口(单独拆分)
app.post('/register', async (req, res) => {
  try {
    const { username, password } = req.body;
    if (!username || !password) {
      return res.status(400).send({ message: '用户名和密码不能为空' });
    }

    // 检查用户是否已存在
    const existingUser = await dbo.collection("data").findOne({ username });
    if (existingUser) {
      return res.status(409).send({ message: '用户名已存在' });
    }

    // 加密密码
    const hashedPassword = await bcrypt.hash(password, saltRounds);
    await dbo.collection("data").insertOne({ username, password: hashedPassword });

    res.send({ message: '注册成功' });
  } catch (err) {
    console.error(err);
    res.status(500).send({ message: '服务器内部错误' });
  }
});

// 管理员专用用户列表接口(需加权限验证)
app.get('/admin/users', async (req, res) => {
  // 此处需添加管理员权限验证逻辑(如JWT校验)
  // 示例:
  // const authHeader = req.headers.authorization;
  // if (!authHeader || !authHeader.startsWith('Bearer ')) {
  //   return res.status(403).send({ message: '无权限访问' });
  // }
  // const token = authHeader.split(' ')[1];
  // 验证token并检查用户是否为管理员...

  try {
    // 查询时排除密码字段
    const users = await dbo.collection("data").find({}, { projection: { password: 0 } }).toArray();
    res.send(users);
  } catch (err) {
    console.error(err);
    res.status(500).send({ message: '服务器内部错误' });
  }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 14:50:27