Overview
您可以使用 Node.js 驱动程序通过一组称为正在使用的加密的功能来加密特定文档字段。通过正在使用的加密,您的应用程序在将数据发送到 MongoDB之前 对数据进行加密,并使用加密字段查询文档。
警告
MongoDB 8.2已知问题
mongocryptd 的 8.2.0 版本可能无法在Windows上运行。如果您在启动 mongocryptd 时指定 --logpath NUL 参数,此错误会影响驱动程序的“正在使用的加密” 。
正在使用的加密可以防止未经授权的用户查看发送到 MongoDB 或位于加密数据库中的明文数据。要在应用程序中启用正在使用的加密并授权其解密数据,必须创建只有应用程序才能访问的加密密钥。只有有权访问加密密钥的应用程序才能访问解密的明文数据。如果攻击者获得对数据库的访问权限,他们只能看到加密的密文数据,因为他们无法访问加密密钥。
您可以使用正在使用的加密来加密 MongoDB 文档中包含以下类型敏感数据的字段:
信用卡号码
地址
健康信息
财务信息
任何其他敏感信息或个人身份信息 (PII)
MongoDB 提供以下功能来启用正在使用的加密:
可查询加密
Queryable Encryption (QE) 是一种正在使用的加密功能,可让您对加密字段值运行查询,包括相等、范围、前缀、后缀和子字符串查询。范围查询支持需要 MongoDB Server 8.0 或更高版本。前缀、后缀和子字符串查询支持需要 MongoDB Server 9.0 或更高版本。
要学习;了解有关Queryable Encryption的更多信息,请参阅MongoDB Server手册中的Queryable Encryption 。
客户端字段级加密 (Client-Side Field Level Encryption)
在 MongoDB Server 4.2 版中引入客户端字段级加密 (CSFLE),支持搜索加密字段的相等性。CSFLE 与 Queryable Encryption 的不同之处在于,您可以选择确定性或随机加密算法来加密字段。 使用 CSFLE 时只能查询使用确定性加密算法的加密字段。当使用随机加密算法对 CSFLE 的字段进行加密时,可以解密这些字段,但不能对这些字段进行相等性查询。使用 Queryable Encryption 时,不能指定加密算法,但可以查询所有加密字段。
当您确定性地加密一个值时,相同的输入值会产生相同的输出值。虽然确定性的加密允许您对这些加密字段执行查询,但关联基数较低的加密数据很容易因频率分析而遭遇密码破解。
要了解有关 CSFLE 的更多信息,请参阅服务器手册中的 CSFLE。
聚合管道支持
从MongoDB Server 8.1 开始,您可以将 $lookup聚合阶段与配置为正在使用的加密的客户端一起使用。此功能需要 mongodb-client-encryption包版本 6.3.0 或更高版本。
$lookup 阶段允许您跨加密集合连接相关数据,而无需在应用程序代码中手动获取和组合文档。源集合和 from集合都必须配置为正在使用的加密。localField 和 foreignField 中指定的字段不得是加密字段。
以下示例展示了对加密集合执行的 $lookup 操作:
const pipeline = [ { $lookup: { from: "encryptedCollection", localField: "userId", foreignField: "_id", as: "userDetails" } } ]; const results = await collection.aggregate(pipeline).toArray();
通过HTTP代理路由KMS请求
从 Node.js驾驶员版本 7.6 开始,您可以通过HTTP 代理将 Node.js驾驶员向密钥管理系统 (KMS ) 发出的请求路由。当您的环境需要出站KMS流量通过HTTP转发代理时,请使用此功能。 proxyOptions 设置仅支持 SOCKS5协议,不包括这种情况。
要控制驾驶员连接到KMS托管的方式,请在 ClientEncryptionOptions对象或 AutoEncryptionOptions对象上设立kmsConnectCallback 选项。设立此选项后,驾驶员会调用回调,而不是连接到KMS托管本身。该回调接收以下属性:
属性 | 说明 |
|---|---|
| 驾驶员必须访问的KMS托管的主机名。 |
| 驾驶员必须访问的KMS托管端口。 |
| 操作的客户端操作超时 (CSOT) 预算中的剩余时间(以毫秒为单位)。如果操作未配置 CSOT,则此属性为 |
| 当连接尝试超过超时预算时中止的 |
以下示例定义了一个回调,该回调通过向代理发送HTTP CONNECT请求来打开通往KMS托管的隧道,然后将该回调传递给 ClientEncryption实例:
import * as net from "net"; const kmsConnectCallback = ({ host, port, timeoutMS, signal }) => new Promise((resolve, reject) => { // Opens a plain connection to the proxy, not to the KMS host. // Passing signal lets Node abort the connection attempt when the // driver's timeout budget expires. const socket = net.connect({ host: "proxy.example.com", port: 8080, signal }); // Applies the remaining CSOT budget to the proxy handshake, so that // a proxy that accepts the connection but never answers CONNECT // can't stall the operation. if (timeoutMS !== undefined) { socket.setTimeout(timeoutMS, () => { socket.destroy(); reject(new Error("Timed out waiting for the proxy")); }); } socket.once("error", reject); socket.once("connect", () => { // Asks the proxy to tunnel to the KMS host socket.write( `CONNECT ${host}:${port} HTTP/1.1\r\n` + `Host: ${host}:${port}\r\n\r\n` ); socket.once("data", chunk => { if (chunk.toString("utf8").startsWith("HTTP/1.1 200")) { // Clears the handshake timeout and returns the socket so that // the driver can perform the TLS handshake socket.setTimeout(0); resolve(socket); } else { socket.destroy(); reject(new Error("Proxy refused the CONNECT request")); } }); }); }); const clientEncryption = new ClientEncryption(keyVaultClient, { keyVaultNamespace, kmsProviders, kmsConnectCallback });
signal属性适用于与代理的连接,timeoutMS属性适用于 CONNECT 交换。在 CONNECT 交换结束后,套接字超时保持活动状态,因此在解析承诺之前清除超时。否则,驾驶员执行 TLS 握手时,超时可能会破坏套接字。
前面的示例已压缩以显示调用顺序。在生产代码中,缓冲代理的响应,直到收到标头区块的末尾,因为响应可以跨多个数据段到达。
重要
kmsConnectCallback 和 proxyOptions 选项是互斥的。如果设立kmsConnectCallback 并在 proxyOptions 中指定 proxyHost 值,则驾驶员会引发 MongoCryptInvalidArgumentError。