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

Node.js用户数据更新异常:仅测试账户可更新数据的问题排查

问题描述

用多个账户测试Node.js应用时,明明登录的是其他用户,更新操作却只会修改测试账户的description字段。重写代码后问题依旧,怀疑是user-controller.js和user-service.js的数据传递出了问题。

相关代码如下:

router.js

router.put('/updateUser/:id', userController.update);

controller.js

class UserController {
 async updateUser(req, res, next) {
        try {
            const userUpdate = await userService.update(req);
            return res.json(userUpdate);
        } catch (e) {
            next(e);
        }
    }
}

service.js

class UserService {
 async updateUser(req) {
    const userUpdate = await UserModel.findOneAndUpdate(
      req.params.id,
      req.body.user,
      { new: true }
    );
    const userDto = new UserDto(userUpdate);
    return { user: userDto };
  }
}

user-dto.js

module.exports = class UserDto {
    email;
    id;
    description;

    constructor(model) {
        this.email = model.email;
        this.id = model._id;
        this.description = model.description
    }
}

user-model.js

const UserSchema = new Schema({
  email: { type: String, unique: true, required: true },
  password: { type: String, required: true },
  description: {
    city: { type: String },
    brand: { type: String },
  },
});

问题分析与修复方案

1. 路由与控制器方法不匹配

router里配置的是调用userController.update,但控制器里的方法名是updateUser,这会导致请求无法触发正确的处理逻辑,可能走错误分支或直接报错。

修复:
修改router.js中的方法映射:

router.put('/updateUser/:id', userController.updateUser);

2. Mongoose更新语法错误

findOneAndUpdate的第一个参数需要是查询条件对象,直接传req.params.id的话,Mongoose会把它当成{ 'req.params.id': undefined }处理,根本定位不到正确用户,甚至可能错误匹配到测试账户。

修复:
在service.js中修正查询条件:

async updateUser(req) {
  const userUpdate = await UserModel.findOneAndUpdate(
    { _id: req.params.id }, // 改为按_id查询的对象
    req.body.user,
    { 
      new: true, 
      runValidators: true // 可选:开启更新时的Schema校验,避免非法数据
    }
  );

  // 增加错误处理,避免更新不存在的用户
  if (!userUpdate) {
    throw new Error('目标用户不存在');
  }

  const userDto = new UserDto(userUpdate);
  return { user: userDto };
}

3. 缺失登录用户身份校验(核心问题)

当前代码完全依赖URL参数里的id决定更新哪个用户,没有校验当前登录用户ID和目标ID是否一致。也就是说,只要请求里传测试账户的ID,不管登录的是谁,都会更新测试账户的数据——这就是问题的根本原因。

修复:

第一步:确保路由经过登录校验

假设你有登录认证中间件(比如JWT校验、Passport),先把路由保护起来:

// router.js
// authMiddleware是你的登录校验中间件,执行后req.user会包含当前登录用户的信息
router.put('/updateUser/:id', authMiddleware, userController.updateUser);

第二步:在控制器中校验身份一致性

// controller.js
async updateUser(req, res, next) {
  try {
    // 检查当前登录用户ID和要更新的用户ID是否一致
    if (req.user.id !== req.params.id) {
      return res.status(403).json({ message: '无权修改该用户的数据' });
    }

    const userUpdate = await userService.update(req);
    return res.json(userUpdate);
  } catch (e) {
    next(e);
  }
}

4. 验证前端请求数据格式

确认前端发送的请求体结构和Schema匹配,比如更新description时,请求体应该是:

{
  "user": {
    "description": {
      "city": "上海",
      "brand": "新品牌"
    }
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 03:30:52