node.js - Mongoose 加密中间件聚合后不调用

标签 node.js mongodb encryption plugins mongoose

我有一个带有“mongoose-encryption”插件的 mongoose 模式,例如:

let someSchema = new Schema({name, age});

someSchema.plugin(mongoose-encryption, {
        encryptionKey: 'eKey',
        signingKey: 'sKey',
        encryptedFields: ['age'],
        decryptPostSave: false
    });

启动模型和存储库后,我尝试聚合一些查询:

let aggregation = []; // just return all the docs.
someModel.aggregate(aggregation, (err, persons) => {
        return persons;
});

因此,我仍然对年龄字段进行了加密,很少有阅读表明聚合后未调用“init”事件的“post”方法(如此处解释 - Mongoose Middleware Docs)。

有好的解决办法吗?或任何其他解决方法?

  • 数据必须加密。

  • 还需要聚合(在现实生活中 - 查找其他集合)

最佳答案

因为我没有找到更好的答案,所以我更改了我的代码(不幸的是作为解决方法)来自己解密对象 - 聚合完成后使用mongoose-encryption的代码解密。

大部分代码取自 GitHub(在我的代码中称为 decryptOne): decryptSync function of mongoose-encryption

“棘手”的事情是解密内部查找值 - 内部文档也有应该解密的“_ct”字段。

let lookup: { [innerField: string]: string[]; } = {
                    user: ['bio']
                };
this.decryptAggregation(aggregationResult, lookup);

我的函数在解密后获取已知查找集合及其所需字段的字典。在那个例子中,另一个名为 users 的集合及其加密字段只是他的简历。

decryptAggregation(res: any[], innerLookup: { [innerField: string]: string[]; }) {
    for (let doc of res) {
        this.decryptSync(doc, innerLookup);
    }
}

private decryptSync(doc: any, innerLookup: { [innerField: string]: string[]; }) {
    this.decryptOne(doc, this.encryptedFields);
    for (let innerObj in innerLookup) {
        if (innerLookup.hasOwnProperty(innerObj)) {
            this.decryptOne(doc[innerObj], innerLookup[innerObj]);
        }
    }
};

private decryptOne(doc: any, fields: string[]) {
    let ct, ctWithIV, decipher, iv, idString, decryptedObject, decryptedObjectJSON, decipheredVal;

    if (doc._ct) {
        ctWithIV = doc._ct.hasOwnProperty('buffer') ? doc._ct.buffer : doc._ct;
        iv = ctWithIV.slice(this.VERSION_LENGTH, this.VERSION_LENGTH + this.IV_LENGTH);
        ct = ctWithIV.slice(this.VERSION_LENGTH + this.IV_LENGTH, ctWithIV.length);

        decipher = crypto.createDecipheriv(this.ENCRYPTION_ALGORITHM, this.encryptionKey, iv);
        try {
            decryptedObjectJSON = decipher.update(ct, undefined, 'utf8') + decipher.final('utf8');
            decryptedObject = JSON.parse(decryptedObjectJSON);
        } catch (err) {
            if (doc._id) {
                idString = doc._id.toString();
            } else {
                idString = 'unknown';
            }
            throw new Error('Error parsing JSON during decrypt of ' + idString + ': ' + err);
        }

        fields.forEach((field) => {
            decipheredVal = mpath.get(field, decryptedObject);

            //JSON.parse returns {type: "Buffer", data: Buffer} for Buffers
            //https://nodejs.org/api/buffer.html#buffer_buf_tojson
            if (_.isObject(decipheredVal) && decipheredVal.type === "Buffer") {
                this.setFieldValue(doc, field, decipheredVal.data);
            } else {
                this.setFieldValue(doc, field, decipheredVal);
            }
        });

        doc._ct = undefined;
        doc._ac = undefined;
    }
}

在完成这些功能后,我完全解密了我想要的对象,最后要做的是将想要的字段投影回客户端 - 使用 lodash.pick

关于node.js - Mongoose 加密中间件聚合后不调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44246161/

相关文章:

node.js - 在firebase功能管理sdk中找不到服务帐户

mongodb - Meteor 通过 mongodb 手动将用户添加到角色

node.js - 如何获取登录用户的对象数组的总和

linux - 从 bash 脚本向 Mongo shell 传递命令,而不停止交互式 Mongo shell

swift - 如何在 AES CryptoSwift 密码后将字节转换为 NSString

node.js - 如何在 node.js 中接收 socket.io 客户端事件?

javascript - 如何在每个具有多个 vCPU 的多个 Google App Engine 实例之间共享缓存?

java - 从 Node.js 应用程序调用 java 程序

javascript - 无法找到nodejs加密代码的浏览器js代码

c# - AES解密 输入数据不是一个完整的 block