Mongoose数组中getter解密失效问题求助
解决Mongoose数组/嵌套文档中加密字段无法解密的问题
嘿,我之前也碰到过一模一样的问题!核心原因是:Mongoose默认只会对顶层文档的字段触发getters/setters,数组里的嵌套子文档不会自动继承父Schema的getters: true配置——这就是为什么你的firstname能正常解密,而数组里的address1还保持加密状态的原因。
下面给你两种直接可行的解决方案:
方案一:给嵌套子文档单独定义Schema并启用Getters
这是最规范的做法,把地址子文档抽成独立的Schema,单独配置toObject和toJSON的getters规则,确保子文档的字段也能触发解密逻辑:
var mongoose = require('mongoose'), Schema = mongoose.Schema; var crypto = require('crypto'); var connection = mongoose.connection; // 1. 先定义地址子文档的Schema,单独配置getters const addressSchema = new Schema({ addressRef: {type: String, trim: true}, address1: {type: String, trim: true, get: decrypt, set: encrypt}, postcode: {type: String, trim: true} }, { toObject: { getters: true }, toJSON: { getters: true } }); // 2. 主文档Schema使用子文档Schema var memberSchema = new Schema({ title: {type: String, trim: true}, firstname: {type: String, trim: true, get: decrypt, set: encrypt}, lastname: {type: String, trim: true}, address: [addressSchema], // 替换成子文档Schema // ...其他字段 }, { collection: 'memberStage', toObject: { getters: true }, toJSON: { getters: true } }); // 加密解密函数保持不变 function encrypt(text){ var cipher = crypto.createCipher('aes-256-cbc', 'test'); var crypted = cipher.update(text,'utf8','hex'); crypted += cipher.final('hex'); return crypted; }; function decrypt(text){ if (text === null || typeof text === 'undefined') { return text; }; var decipher = crypto.createDecipher('aes-256-cbc', 'test'); var dec = decipher.update(text,'hex','utf8'); dec += decipher.final('utf8'); return dec; }; module.exports = connection.model('memberStage', memberSchema);
这样每个地址子文档都会独立触发getters,address1就能正常解密了。
方案二:查询后手动遍历数组触发解密
如果不想修改Schema结构,也可以在查询返回后手动处理数组字段,调用解密函数:
member.find(query, function(err, members){ // 遍历每个成员,手动处理address数组 const processedData = members.map(member => { // 先把文档转成普通对象,触发顶层字段的getters const memberObj = member.toObject({ getters: true }); // 再遍历address数组,手动解密address1 memberObj.address = memberObj.address.map(addr => { if (addr.address1) { addr.address1 = decrypt(addr.address1); } return addr; }); return memberObj; }); res.status(200).json({ meta : { success: true, message: 'Member Data'}, data : processedData }); });
这种方法适合临时修复,但如果嵌套结构复杂、字段多的话,维护起来会比较麻烦。
额外提醒
别把加密密钥硬编码在代码里!建议用环境变量(比如process.env.ENCRYPTION_KEY)来存储密钥,避免代码泄露导致加密数据被破解。
内容的提问来源于stack exchange,提问作者Mish
相关产品推荐
相关产品推荐

