Sequelize MySQL中如何实现未提供密码时不更新对应表字段
解决方案
方案原理
通过「请求层参数过滤」+「Schema层钩子加固」双重逻辑实现,既避免无效字段传入更新逻辑,也从模型底层防止密码被意外覆盖。
第一步:优化更新请求的参数构造
你当前的更新代码无论用户是否传入密码,都把password字段放入更新对象,用户没传值时这个字段会是undefined或空字符串,可能触发意外更新。可以先动态构造更新字段:
// 先构造不需要密码的基础更新字段 const updateFields = { cash_credit: req.body.cash_credit, name: req.body.name, address: req.body.address, state_id: req.body.state_id, gstin: req.body.gstin, mobile: req.body.mobile, phone: req.body.phone, email: req.body.email, form_type: req.body.form_type, pincode: req.body.pincode, city_id: req.body.city_id, country: req.body.country || 0, id: req.body.id } // 仅当用户传入非空密码时,才把密码加入更新字段 if (req.body.password && req.body.password.trim()) { updateFields.password = req.body.password } // 执行更新 db.customers.findOne({ where: { id: req.body.id } }).then(data => { data.update(updateFields).then(data2 => { console.log(data2); }); });
第二步:加固Schema的beforeUpdate钩子
你当前的钩子逻辑存在边界漏洞:如果用户传入空字符串密码、或者意外把undefined传入更新,可能触发异常。修改钩子逻辑如下:
beforeUpdate: async (schema, options) => { // 仅当密码字段被显式修改、且值不为空时,才重新哈希更新 if (schema.changed('password') && schema.password) { let hashedPassword = await bcrypt.hash(schema.password, saltRounds); schema.password = hashedPassword; } else { // 否则恢复为数据库中存储的原有密码值 schema.password = schema.previous('password'); } }
其中changed('password')是Sequelize内置方法,用来判断本次更新是否显式修改了password字段;previous('password')可以拿到更新前数据库中存储的原始密码值,双重保障不会覆盖原有密码。
额外说明
你当前配置的defaultScope默认排除password字段是合理的,日常查询不会返回敏感的密码字段,无需修改。
内容的提问来源于stack exchange,提问作者Sariful
相关产品推荐
相关产品推荐

