client-side-field-level-encryption"> client-side-field-level-encryption"> 集成 MongoDB 客户端字段级加密
客户端字段级加密,简称 CSFLE,是一种在 MongoDB 中以加密格式存储数据的工具。例如,您不是以纯文本字符串形式存储 name
属性,CSFLE 表示 MongoDB 会将您的文档存储为带有 name
的加密缓冲区。对于无法解密数据的客户端,生成的文档将类似于以下内容。
{
"_id" : ObjectId("647a3207661e3a3a1bc3e614"),
"name" : BinData(6,"ASrIv7XfokKwiCUJEjckOdgCG+u6IqavcOWX8hINz29MLvcKDZ4nnjCnPFZG+0ftVxMdWgzu6Vdh7ys1uIK1WiaPN0SqpmmtL2rPoqT9gfhADpGDmI60+vm0bJepXNY1Gv0="),
"__v" : 0
}
您可以在 MongoDB CSFLE 文档 和 关于 CSFLE 在 Node.js 中的这篇博文 中了解更多关于 CSFLE 的信息。
请注意,Mongoose 目前**没有**任何特定于 Mongoose 的 CSFLE API。Mongoose 将所有与 CSFLE 相关的工作委托给 MongoDB Node.js 驱动程序,因此 autoEncryption
选项 用于 mongoose.connect()
和 mongoose.createConnection()
是您放置所有与 CSFLE 相关的配置的位置。Mongoose 模式目前不支持 CSFLE 配置。
使用 Mongoose 设置字段级加密
首先,您需要安装 mongodb-client-encryption npm 包。这是 MongoDB 用于设置加密密钥的官方软件包。
npm install mongodb-client-encryption
您还需要确保已安装 mongocryptd。mongocryptd 是与 MongoDB 服务器不同的进程,您需要运行它才能使用字段级加密。您可以自己运行 mongocryptd,也可以确保它在系统 PATH 上,MongoDB Node.js 驱动程序将为您运行它。 您可以在此处阅读有关 mongocryptd 的更多信息。
设置并运行 mongocryptd 后,首先需要创建新的加密密钥,如下所示。请记住,以下示例只是一个简单的示例,可帮助您入门。以下示例中的加密密钥不安全;MongoDB 建议使用 KMS。
const { ClientEncryption } = require('mongodb-client-encryption');
const mongoose = require('mongoose');
const { Binary } = require('mongodb');
run().catch(err => console.log(err));
async function run() {
/* Step 1: Connect to MongoDB and insert a key */
// Create a very basic key. You're responsible for making
// your key secure, don't use this in prod :)
const arr = [];
for (let i = 0; i < 96; ++i) {
arr.push(i);
}
const key = Buffer.from(arr);
const keyVaultNamespace = 'client.encryption';
const kmsProviders = { local: { key } };
const uri = 'mongodb://127.0.0.1:27017/mongoose_test';
const conn = await mongoose.createConnection(uri, {
autoEncryption: {
keyVaultNamespace,
kmsProviders
}
}).asPromise();
const encryption = new ClientEncryption(conn.client, {
keyVaultNamespace,
kmsProviders,
});
const _key = await encryption.createDataKey('local');
}
获得加密密钥后,您可以使用具有 schemaMap
的独立 Mongoose 连接来创建连接,该连接使用 JSON 模式语法定义哪些字段被加密,如下所示。
/* Step 2: connect using schema map and new key */
await mongoose.connect('mongodb://127.0.0.1:27017/mongoose_test', {
// Configure auto encryption
autoEncryption: {
keyVaultNamespace,
kmsProviders,
schemaMap: {
'mongoose_test.tests': {
bsonType: 'object',
encryptMetadata: {
keyId: [_key]
},
properties: {
name: {
encrypt: {
bsonType: 'string',
algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'
}
}
}
}
}
}
});
使用上述连接,如果您创建名为“Test”并使用“tests”集合的模型,则所有文档的 name
属性都将被加密。
// 'super secret' will be stored as 'BinData' in the database,
// if you query using the `mongo` shell.
const Model = mongoose.model('Test', mongoose.Schema({ name: String }));
await Model.create({ name: 'super secret' });