快速入门
Overview
本指南将展示如何构建一个实现 MongoDB Queryable Encryption 功能的应用程序,以自动加密和解密文档字段。
在右侧的下拉菜单中选择您的驱动程序语言,了解如何创建自动加密和解密文档字段的应用程序。
重要
请勿在生产环境中使用此示例应用程序
本教程中的操作说明包括在不安全的环境中存储加密密钥,因此您不应在生产环境中使用此应用程序的未修改版本。在生产环境中使用此应用程序存在以下风险:未经授权访问加密密钥或丢失解密数据所需的密钥。本教程旨在演示如何使用 Queryable Encryption,而无需设置密钥管理系统。
您可以使用密钥管理系统将加密密钥安全地存储在生产环境中。 KMS是一种远程服务,可安全地存储和管理加密密钥。 要学习;了解如何设立使用KMS且启用了Queryable Encryption的应用程序,请参阅 Queryable Encryption教程。
开始之前
要完成并运行本指南中的代码,您需要设置开发环境,如“安装 Queryable Encryption 兼容驱动程序”页面中所示。
完整应用程序代码
要查看示例应用程序的完整代码,请在语言选择器中选择您的编程语言。
步骤
分配应用程序变量
本教程中的代码示例使用以下变量来执行 Queryable Encryption 工作流:
kmsProviderName - 您用于存储客户主密钥的KMS 。在本教程中,将此变量设置为
"local"
。uri - 您的MongoDB 部署连接 URI。 在
MONGODB_URI
环境变量中设置连接 URI 或直接替换该值。keyVaultDatabaseName - MongoDB 中将存储您的数据加密密钥 (DEK) 的数据库。将此变量设置为
"encryption"
。keyVaultCollectionName - MongoDB中将存储您的 DEK 的集合。 将此变量设置为
"__keyVault"
,这是一种约定,有助于防止将其误认为是用户集合。keyVaultNamespace - MongoDB中将存储您的 DEK 的命名空间。 将此变量设置为
keyVaultDatabaseName
和keyVaultCollectionName
变量的值,并用句点分隔。cryptoDatabaseName - MongoDB 中将存储您的加密数据的数据库。将此变量设置为
"medicalRecords"
。cryptoCollectionName - MongoDB 中将存储您的加密数据的集合。将此变量设置为
"patients"
。
您可以使用以下代码来声明这些变量:
// KMS provider name should be one of the following: "aws", "gcp", "azure", "kmip" or "local" const kmsProviderName = "<Your KMS Provider Name>"; const uri = process.env.MONGODB_URI; // Your connection URI const keyVaultDatabaseName = "encryption"; const keyVaultCollectionName = "__keyVault"; const keyVaultNamespace = `${keyVaultDatabaseName}.${keyVaultCollectionName}`; const encryptedDatabaseName = "medicalRecords"; const encryptedCollectionName = "patients";
kmsProviderName - 您用来存储客户主密钥的 KMS。 在本教程中,请将此值设置为
"local"
。keyVaultDatabaseName - MongoDB 中将存储您的数据加密密钥 (DEK) 的数据库。 将
keyVaultDatabaseName
的值设置为"encryption"
。keyVaultCollectionName - MongoDB中将存储您的 DEK 的集合。 将此变量设置为
"__keyVault"
,这是一种约定,有助于防止将其误认为是用户集合。keyVaultNamespace - MongoDB 中将存储您的 DEK 的命名空间。 将
keyVaultNamespace
设置为新的CollectionNamespace
对象,其名称是keyVaultDatabaseName
和keyVaultCollectionName
变量的值,用句点分隔。cryptoDatabaseName - MongoDB 中将存储您的加密数据的数据库。 将
encryptedDatabaseName
的值设置为"medicalRecords"
。encryptedCollectionName - MongoDB 中将存储您的加密数据的 collection。将
encryptedCollectionName
的值设置为"patients"
。uri - 您的 MongoDB 部署连接 URI。 在
appsettings.json
文件中设置连接 URI 或直接替换该值。
您可以使用以下代码来声明这些变量:
// KMS provider name should be one of the following: "aws", "gcp", "azure", "kmip" or "local" const string kmsProviderName = "<your KMS provider name>"; const string keyVaultDatabaseName = "encryption"; const string keyVaultCollectionName = "__keyVault"; var keyVaultNamespace = CollectionNamespace.FromFullName($"{keyVaultDatabaseName}.{keyVaultCollectionName}"); const string encryptedDatabaseName = "medicalRecords"; const string encryptedCollectionName = "patients"; var appSettings = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); var uri = appSettings["MongoDbUri"];
kmsProviderName - 您用于存储客户主密钥的KMS 。 在本教程中,将此变量设置为
"local"
。uri - 您的MongoDB 部署连接 URI。 在
MONGODB_URI
环境变量中设置连接 URI 或直接替换该值。keyVaultDatabaseName - MongoDB 中将存储您的数据加密密钥 (DEK) 的数据库。将此变量设置为
"encryption"
。keyVaultCollectionName - MongoDB中将存储您的 DEK 的集合。 将此变量设置为
"__keyVault"
,这是一种约定,有助于防止将其误认为是用户集合。keyVaultNamespace - MongoDB中将存储您的 DEK 的命名空间。 将此变量设置为
keyVaultDatabaseName
和keyVaultCollectionName
变量的值,并用句点分隔。cryptoDatabaseName - MongoDB 中将存储您的加密数据的数据库。将此变量设置为
"medicalRecords"
。cryptoCollectionName - MongoDB 中将存储您的加密数据的集合。将此变量设置为
"patients"
。
您可以使用以下代码来声明这些变量:
// KMS provider name should be one of the following: "aws", "gcp", "azure", "kmip" or "local" kmsProviderName := "<KMS provider name>" uri := os.Getenv("MONGODB_URI") // Your connection URI keyVaultDatabaseName := "encryption" keyVaultCollectionName := "__keyVault" keyVaultNamespace := keyVaultDatabaseName + "." + keyVaultCollectionName encryptedDatabaseName := "medicalRecords" encryptedCollectionName := "patients"
kmsProviderName - 您用于存储客户主密钥的KMS 。 在本教程中,将此变量设置为
"local"
。uri - 您的MongoDB 部署连接 URI。 在
MONGODB_URI
环境变量中设置连接 URI 或直接替换该值。keyVaultDatabaseName - MongoDB 中将存储您的数据加密密钥 (DEK) 的数据库。将此变量设置为
"encryption"
。keyVaultCollectionName - MongoDB中将存储您的 DEK 的集合。 将此变量设置为
"__keyVault"
,这是一种约定,有助于防止将其误认为是用户集合。keyVaultNamespace - MongoDB中将存储您的 DEK 的命名空间。 将此变量设置为
keyVaultDatabaseName
和keyVaultCollectionName
变量的值,并用句点分隔。cryptoDatabaseName - MongoDB 中将存储您的加密数据的数据库。将此变量设置为
"medicalRecords"
。cryptoCollectionName - MongoDB 中将存储您的加密数据的集合。将此变量设置为
"patients"
。
您可以使用以下代码来声明这些变量:
// KMS provider name should be one of the following: "aws", "gcp", "azure", "kmip" or "local" String kmsProviderName = "<KMS provider name>"; String uri = QueryableEncryptionHelpers.getEnv("MONGODB_URI"); // Your connection URI String keyVaultDatabaseName = "encryption"; String keyVaultCollectionName = "__keyVault"; String keyVaultNamespace = keyVaultDatabaseName + "." + keyVaultCollectionName; String encryptedDatabaseName = "medicalRecords"; String encryptedCollectionName = "patients";
kmsProviderName - 您用于存储客户主密钥的KMS 。 在本教程中,将此变量设置为
"local"
。uri - 您的MongoDB 部署连接 URI。 在
MONGODB_URI
环境变量中设置连接 URI 或直接替换该值。keyVaultDatabaseName - MongoDB 中将存储您的数据加密密钥 (DEK) 的数据库。将此变量设置为
"encryption"
。keyVaultCollectionName - MongoDB中将存储您的 DEK 的集合。 将此变量设置为
"__keyVault"
,这是一种约定,有助于防止将其误认为是用户集合。keyVaultNamespace - MongoDB中将存储您的 DEK 的命名空间。 将此变量设置为
keyVaultDatabaseName
和keyVaultCollectionName
变量的值,并用句点分隔。cryptoDatabaseName - MongoDB 中将存储您的加密数据的数据库。将此变量设置为
"medicalRecords"
。cryptoCollectionName - MongoDB 中将存储您的加密数据的集合。将此变量设置为
"patients"
。
您可以使用以下代码来声明这些变量:
// KMS provider name should be one of the following: "aws", "gcp", "azure", "kmip" or "local" const kmsProviderName = "<Your KMS Provider Name>"; const uri = process.env.MONGODB_URI; // Your connection URI const keyVaultDatabaseName = "encryption"; const keyVaultCollectionName = "__keyVault"; const keyVaultNamespace = `${keyVaultDatabaseName}.${keyVaultCollectionName}`; const encryptedDatabaseName = "medicalRecords"; const encryptedCollectionName = "patients";
kms_provider_name - 您用来存储客户主密钥的KMS 。 在本教程中,将此变量设置为
"local"
。uri - 您的MongoDB 部署连接 URI。 在
MONGODB_URI
环境变量中设置连接 URI 或直接替换该值。key_vault_database_name - MongoDB中将存储您的数据加密密钥 (DEK) 的数据库。 将此变量设置为
"encryption"
。key_vault_collection_name - MongoDB中将存储您的 DEK 的集合。 将此变量设置为
"__keyVault"
,这是一种约定,有助于防止将其误认为是用户集合。key_vault_namespace - MongoDB中存储 DEK 的命名空间。 将此变量设置为
key_vault_database_name
和key_vault_collection_name
变量的值,并用句点分隔。encryption_database_name - MongoDB中将存储您的加密加密的数据库。 将此变量设置为
"medicalRecords"
。encryption_collection_name - MongoDB中将存储您的加密加密的集合。 将此变量设置为
"patients"
。
您可以使用以下代码来声明这些变量:
# KMS provider name should be one of the following: "aws", "gcp", "azure", "kmip" or "local" kms_provider_name = "<KMS provider name>" uri = os.environ['MONGODB_URI'] # Your connection URI key_vault_database_name = "encryption" key_vault_collection_name = "__keyVault" key_vault_namespace = f"{key_vault_database_name}.{key_vault_collection_name}" encrypted_database_name = "medicalRecords" encrypted_collection_name = "patients"
重要
密钥保管库集合命名空间权限
要完成本教程,您的应用程序用于连接到 MongoDB 的数据库用户必须具有对以下命名空间的dbAdmin
权限:
encryption.__keyVault
medicalRecords
database
创建加密集合
创建客户主密钥
您必须创建客户主密钥 (CMK) 才能执行 Queryable Encryption。
创建一个 96 字节的客户主密钥,并将其保存到您的文件系统中,作为文件
customer-master-key.txt
:customerMasterKeyPath = "customer-master-key.txt"; if (!fs.existsSync(customerMasterKeyPath)) { fs.writeFileSync(customerMasterKeyPath, crypto.randomBytes(96)); } using var randomNumberGenerator = RandomNumberGenerator.Create(); try { var bytes = new byte[96]; randomNumberGenerator.GetBytes(bytes); var localCustomerMasterKeyBase64 = Convert.ToBase64String(bytes); File.WriteAllText("customer-master-key.txt", localCustomerMasterKeyBase64); } catch (Exception e) { throw new Exception("Unable to write Customer Master Key file due to the following error: " + e.Message); } key := make([]byte, 96) if _, err := rand.Read(key); err != nil { panic(fmt.Sprintf("Unable to create a random 96 byte data key: %v\n", err)) } if err := os.WriteFile("customer-master-key.txt", key, 0644); err != nil { panic(fmt.Sprintf("Unable to write key to file: %v\n", err)) } byte[] localCustomerMasterKey = new byte[96]; new SecureRandom().nextBytes(localCustomerMasterKey); try (FileOutputStream stream = new FileOutputStream("customer-master-key.txt")) { stream.write(localCustomerMasterKey); // ... if (!existsSync("./customer-master-key.txt")) { try { writeFileSync("customer-master-key.txt", randomBytes(96)); } catch (err) { throw new Error( `Unable to write Customer Master Key to file due to the following error: ${err}` ); } } path = "customer-master-key.txt" file_bytes = os.urandom(96) with open(path, "wb") as f: f.write(file_bytes) 警告
保护生产环境中的本地密钥文件
提示
从命令行生成 CMK
使用以下命令从 Unix Shell 或 PowerShell 生成 CMK :
Unix shell:
echo $(head -c 96 /dev/urandom | base64 | tr -d '\n') PowerShell:
$r=[byte[]]::new(64);$g=[System.Security.Cryptography.RandomNumberGenerator]::Create();$g.GetBytes($r);[Convert]::ToBase64String($r)
将上述命令的输出保存到名为
customer-master-key.txt
的文件中。检索客户主密钥并指定 KMS 提供商设置
检索您在本指南的创建客户主密钥步骤中生成的客户主密钥文件的内容。
使用KMS提供商设置中的集合扫描值。客户端使用这些设置来发现集合扫描 。将提供商名称设置为
local
,以表明您正在使用本地密钥提供程序。// WARNING: Do not use a local key file in a production application const localMasterKey = fs.readFileSync("./customer-master-key.txt"); if (localMasterKey.length !== 96) { throw new Error( "Expected the customer master key file to be 96 bytes." ); } kmsProviderCredentials = { local: { key: localMasterKey, }, }; // WARNING: Do not use a local key file in a production application var kmsProviderCredentials = new Dictionary<string, IReadOnlyDictionary<string, object>>(); try { var localCustomerMasterKeyBase64 = File.ReadAllText("customer-master-key.txt"); var localCustomerMasterKeyBytes = Convert.FromBase64String(localCustomerMasterKeyBase64); if (localCustomerMasterKeyBytes.Length != 96) { throw new Exception("Expected the customer master key file to be 96 bytes."); } var localOptions = new Dictionary<string, object> { { "key", localCustomerMasterKeyBytes } }; kmsProviderCredentials.Add("local", localOptions); } key, err := os.ReadFile("customer-master-key.txt") if err != nil { panic(fmt.Sprintf("Could not read the Customer Master Key: %v", err)) } if len(key) != 96 { panic(fmt.Sprintf("Expected the customer master key file to be 96 bytes.")) } kmsProviderCredentials := map[string]map[string]interface{}{"local": {"key": key}} byte[] localCustomerMasterKey = new byte[96]; try (FileInputStream fis = new FileInputStream("customer-master-key.txt")) { if (fis.read(localCustomerMasterKey) != 96) throw new Exception("Expected the customer master key file to be 96 bytes."); } catch (Exception e) { throw new Exception("Unable to read the Customer Master Key due to the following error: " + e.getMessage()); } Map<String, Object> keyMap = new HashMap<String, Object>(); keyMap.put("key", localCustomerMasterKey); Map<String, Map<String, Object>> kmsProviderCredentials = new HashMap<String, Map<String, Object>>(); kmsProviderCredentials.put("local", keyMap); // WARNING: Do not use a local key file in a production application const localMasterKey = readFileSync("./customer-master-key.txt"); if (localMasterKey.length !== 96) { throw new Error( "Expected the customer master key file to be 96 bytes." ); } kmsProviders = { local: { key: localMasterKey, }, }; path = "./customer-master-key.txt" with open(path, "rb") as f: local_master_key = f.read() if len(local_master_key) != 96: raise Exception("Expected the customer master key file to be 96 bytes.") kms_provider_credentials = { "local": { "key": local_master_key }, } 设置自动加密选项
创建一个包含以下选项的
autoEncryptionOptions
对象:密钥保管库集合的命名空间
上一步中定义的
kmsProviderCredentials
对象
const autoEncryptionOptions = { keyVaultNamespace: keyVaultNamespace, kmsProviders: kmsProviderCredentials, }; 创建一个包含以下选项的
AutoEncryptionOptions
对象:密钥保管库集合的命名空间
上一步中定义的
kmsProviderCredentials
对象extraOptions
对象,包含以下内容的路径:- 您的自动加密共享库
var extraOptions = new Dictionary<string, object> { { "cryptSharedLibPath", _appSettings["CryptSharedLibPath"] } // Path to your Automatic Encryption Shared Library }; var autoEncryptionOptions = new AutoEncryptionOptions( keyVaultNamespace, kmsProviderCredentials, extraOptions: extraOptions); 创建一个包含以下选项的
AutoEncryption
对象:密钥保管库集合的命名空间
上一步中定义的
kmsProviderCredentials
对象cryptSharedLibraryPath
对象,包含以下内容的路径:- 您的自动加密共享库
cryptSharedLibraryPath := map[string]interface{}{ "cryptSharedLibPath": os.Getenv("SHARED_LIB_PATH"), // Path to your Automatic Encryption Shared Library } autoEncryptionOptions := options.AutoEncryption(). SetKeyVaultNamespace(keyVaultNamespace). SetKmsProviders(kmsProviderCredentials). SetExtraOptions(cryptSharedLibraryPath) 创建一个包含以下选项的
AutoEncryptionSettings
对象:密钥保管库集合的命名空间
上一步中定义的
kmsProviderCredentials
对象extraOptions
对象,包含以下内容的路径:- 您的自动加密共享库
Map<String, Object> extraOptions = new HashMap<String, Object>(); extraOptions.put("cryptSharedLibPath", getEnv("SHARED_LIB_PATH")); // Path to your Automatic Encryption Shared Library AutoEncryptionSettings autoEncryptionSettings = AutoEncryptionSettings.builder() .keyVaultNamespace(keyVaultNamespace) .kmsProviders(kmsProviderCredentials) .extraOptions(extraOptions) .build(); 创建一个包含以下选项的
autoEncryptionOptions
对象:密钥保管库集合的命名空间
上一步中定义的
kmsProviders
对象sharedLibraryPathOptions
对象,包含以下内容的路径:- 您的自动加密共享库
const extraOptions = { cryptSharedLibPath: process.env.SHARED_LIB_PATH, // Path to your Automatic Encryption Shared Library }; const autoEncryptionOptions = { keyVaultNamespace, kmsProviders, extraOptions, }; 创建一个包含以下选项的
AutoEncryptionOpts
对象:上一步中定义的
kms_provider_credentials
对象密钥保管库集合的命名空间
自动加密共享库的路径
auto_encryption_options = AutoEncryptionOpts( kms_provider_credentials, key_vault_namespace, crypt_shared_lib_path=os.environ['SHARED_LIB_PATH'] # Path to your Automatic Encryption Shared Library> ) 创建客户端以设置加密集合
要创建用于对集合中的数据进行加密和解密的客户端,请使用您的连接 URI 和自动加密选项实例化一个新的
MongoClient
。const encryptedClient = Mongo(uri, autoEncryptionOptions); 重要提示:如果使用的是.NET/ C#驱动程序版本3.0 或更高版本,则必须在实例化新的
MongoClient
之前将以下代码添加到应用程序中:MongoClientSettings.Extensions.AddAutoEncryption(); // .NET/C# Driver v3.0 or later only 使用连接 URI 和自动加密选项实例化新的
MongoClient
:var clientSettings = MongoClientSettings.FromConnectionString(uri); clientSettings.AutoEncryptionOptions = qeHelpers.GetAutoEncryptionOptions( keyVaultNamespace, kmsProviderCredentials); var encryptedClient = new MongoClient(clientSettings); encryptedClient, err := mongo.Connect( context.TODO(), options.Client().ApplyURI(uri).SetAutoEncryptionOptions(autoEncryptionOptions), ) if err != nil { panic(fmt.Sprintf("Unable to connect to MongoDB: %v\n", err)) } defer func() { _ = encryptedClient.Disconnect(context.TODO()) }() MongoClientSettings clientSettings = MongoClientSettings.builder() .applyConnectionString(new ConnectionString(uri)) .autoEncryptionSettings(autoEncryptionSettings) .build(); try (MongoClient encryptedClient = MongoClients.create(clientSettings)) { const encryptedClient = new MongoClient(uri, { autoEncryption: autoEncryptionOptions, }); encrypted_client = MongoClient( uri, auto_encryption_opts=auto_encryption_options) 指定要加密的字段
如要加密字段,请将其添加到加密模式中。要启用对字段的查询,请添加“queries”属性。创建加密模式,如下所示:
const encryptedFieldsMap = { encryptedFields: { fields: [ { path: "patientRecord.ssn", bsonType: "string", queries: { queryType: "equality" }, }, { path: "patientRecord.billing", bsonType: "object", }, ], }, }; var encryptedFields = new BsonDocument { { "fields", new BsonArray { new BsonDocument { { "keyId", BsonNull.Value }, { "path", "patientRecord.ssn" }, { "bsonType", "string" }, { "queries", new BsonDocument("queryType", "equality") } }, new BsonDocument { { "keyId", BsonNull.Value }, { "path", "patientRecord.billing" }, { "bsonType", "object" } } } } }; encryptedFieldsMap := bson.M{ "fields": []bson.M{ bson.M{ "keyId": nil, "path": "patientRecord.ssn", "bsonType": "string", "queries": []bson.M{ { "queryType": "equality", }, }, }, bson.M{ "keyId": nil, "path": "patientRecord.billing", "bsonType": "object", }, }, } BsonDocument encryptedFieldsMap = new BsonDocument().append("fields", new BsonArray(Arrays.asList( new BsonDocument() .append("keyId", new BsonNull()) .append("path", new BsonString("patientRecord.ssn")) .append("bsonType", new BsonString("string")) .append("queries", new BsonDocument() .append("queryType", new BsonString("equality"))), new BsonDocument() .append("keyId", new BsonNull()) .append("path", new BsonString("patientRecord.billing")) .append("bsonType", new BsonString("object"))))); const encryptedFieldsMap = { encryptedFields: { fields: [ { path: "patientRecord.ssn", bsonType: "string", queries: { queryType: "equality" }, }, { path: "patientRecord.billing", bsonType: "object", }, ], }, }; encrypted_fields_map = { "fields": [ { "path": "patientRecord.ssn", "bsonType": "string", "queries": [{"queryType": "equality"}] }, { "path": "patientRecord.billing", "bsonType": "object", } ] } 注意
在前面的代码示例中,“ssn”和“billing”字段都经过加密,但只能查询“ssn”字段。
创建集合
实例化
ClientEncryption
以访问加密辅助方法的 API。const clientEncryption = encryptedClient.getClientEncryption(); var clientEncryptionOptions = new ClientEncryptionOptions( keyVaultClient: keyVaultClient, keyVaultNamespace: keyVaultNamespace, kmsProviders: kmsProviderCredentials ); var clientEncryption = new ClientEncryption(clientEncryptionOptions); opts := options.ClientEncryption(). SetKeyVaultNamespace(keyVaultNamespace). SetKmsProviders(kmsProviderCredentials) clientEncryption, err := mongo.NewClientEncryption(encryptedClient, opts) if err != nil { panic(fmt.Sprintf("Unable to create a ClientEncryption instance due to the following error: %s\n", err)) } ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder() .keyVaultMongoClientSettings(MongoClientSettings.builder() .applyConnectionString(new ConnectionString(uri)) .build()) .keyVaultNamespace(keyVaultNamespace) .kmsProviders(kmsProviderCredentials) .build(); ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings); const clientEncryption = new ClientEncryption( encryptedClient, autoEncryptionOptions ); client_encryption = ClientEncryption( kms_providers=kms_provider_credentials, key_vault_namespace=key_vault_namespace, key_vault_client=encrypted_client, codec_options=CodecOptions(uuid_representation=STANDARD) ) 由于您使用的是本地客户主密钥,因此您无需提供客户主密钥凭证。创建一个变量,其中包含一个空对象,用于在您创建加密集合时代替凭证。
customerMasterKeyCredentials = {}; var customerMasterKeyCredentials = new BsonDocument(); cmkCredentials := map[string]string{} BsonDocument customerMasterKeyCredentials = new BsonDocument(); customerMasterKeyCredentials = {}; customer_master_key_credentials = {} 使用可通过
ClientEncryption
类访问的加密助手方法创建加密集合。 此方法自动为加密字段生成数据加密密钥并创建加密集合:await clientEncryption.createEncryptedCollection( encryptedDatabaseName, encryptedCollectionName, { provider: kmsProviderName, createCollectionOptions: encryptedFieldsMap, masterKey: customerMasterKeyCredentials, } ); 本教程的 C# 版本使用单独的类作为 Realm 数据模型来表示文档结构。将以下
Patient
、PatientRecord
和PatientBilling
类添加到您的项目中:using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; [ ]public class Patient { public ObjectId Id { get; set; } public string PatientName { get; set; } public PatientRecord PatientRecord { get; set; } } public class PatientRecord { public string Ssn { get; set; } public PatientBilling Billing { get; set; } public int BillAmount { get; set; } } public class PatientBilling { public string CardType { get; set; } public long CardNumber { get; set; } } 添加这些类后,使用可通过
ClientEncryption
类访问的加密助手方法创建加密collection。此方法自动为字段生成数据加密密钥并创建加密collection:var createCollectionOptions = new CreateCollectionOptions<Patient> { EncryptedFields = encryptedFields }; clientEncryption.CreateEncryptedCollection(patientDatabase, encryptedCollectionName, createCollectionOptions, kmsProviderName, customerMasterKeyCredentials); 创建加密集合的方法需要引用数据库对象,而不是数据库名称。可以通过在客户端对象上使用方法来获取此引用。
本教程的Go版本使用数据模型来表示文档结构。 将以下结构体添加到项目中以表示集合中的数据:
type PatientDocument struct { PatientName string `bson:"patientName"` PatientID int32 `bson:"patientId"` PatientRecord PatientRecord `bson:"patientRecord"` } type PatientRecord struct { SSN string `bson:"ssn"` Billing PaymentInfo `bson:"billing"` BillAmount int `bson:"billAmount"` } type PaymentInfo struct { Type string `bson:"type"` Number string `bson:"number"` } 添加这些类后,使用可通过
ClientEncryption
类访问的加密助手方法创建加密collection。此方法自动为字段生成数据加密密钥并创建加密collection:createCollectionOptions := options.CreateCollection().SetEncryptedFields(encryptedFieldsMap) _, _, err = clientEncryption.CreateEncryptedCollection( context.TODO(), encryptedClient.Database(encryptedDatabaseName), encryptedCollectionName, createCollectionOptions, kmsProviderName, customerMasterKey, ) 创建加密集合的方法需要引用数据库对象,而不是数据库名称。可以通过在客户端对象上使用方法来获取此引用。
使用可通过
ClientEncryption
类访问的加密助手方法创建加密集合。 此方法自动为加密字段生成数据加密密钥并创建加密集合:CreateCollectionOptions createCollectionOptions = new CreateCollectionOptions().encryptedFields(encryptedFieldsMap); CreateEncryptedCollectionParams encryptedCollectionParams = new CreateEncryptedCollectionParams(kmsProviderName); encryptedCollectionParams.masterKey(customerMasterKeyCredentials); try { clientEncryption.createEncryptedCollection( encryptedClient.getDatabase(encryptedDatabaseName), encryptedCollectionName, createCollectionOptions, encryptedCollectionParams); } 创建加密集合的方法需要引用数据库对象,而不是数据库名称。可以通过在客户端对象上使用方法来获取此引用。
使用可通过
ClientEncryption
类访问的加密助手方法创建加密集合。 此方法自动为加密字段生成数据加密密钥并创建加密集合:注意
导入 ClientEncryption
使用 Node.js 驱动程序 v6.0 及更高版本时,必须从
mongodb
导入ClientEncryption
。对于较早的驱动程序版本,请从
mongodb-client-encryption
导入ClientEncryption
。await clientEncryption.createEncryptedCollection( encryptedDatabase, encryptedCollectionName, { provider: kmsProviderName, createCollectionOptions: encryptedFieldsMap, masterKey: customerMasterKeyCredentials, } ); 创建加密集合的方法需要引用数据库对象,而不是数据库名称。可以通过在客户端对象上使用方法来获取此引用。
使用可通过
ClientEncryption
类访问的加密助手方法创建加密集合。 此方法自动为加密字段生成数据加密密钥并创建加密集合:client_encryption.create_encrypted_collection( encrypted_client[encrypted_database_name], encrypted_collection_name, encrypted_fields_map, kms_provider_name, customer_master_key_credentials, ) 创建加密集合的方法需要引用数据库对象,而不是数据库名称。可以通过在客户端对象上使用方法来获取此引用。
插入具有加密字段的文档
创建描述患者个人信息的示例文档。使用加密的客户端将其插入到 patients
集合中,如以下示例所示:
const patientDocument = { patientName: "Jon Doe", patientId: 12345678, patientRecord: { ssn: "987-65-4320", billing: { type: "Visa", number: "4111111111111111", }, billAmount: 1500, }, }; const encryptedCollection = encryptedClient .getDB(encryptedDatabaseName) .getCollection(encryptedCollectionName); const insertResult = await encryptedCollection.insertOne(patientDocument);
创建描述患者个人信息的示例文档。使用加密的客户端将其插入到 patients
集合中,如以下示例所示:
var patient = new Patient { PatientName = "Jon Doe", Id = new ObjectId(), PatientRecord = new PatientRecord { Ssn = "987-65-4320", Billing = new PatientBilling { CardType = "Visa", CardNumber = 4111111111111111, }, BillAmount = 1500 } }; var encryptedCollection = encryptedClient.GetDatabase(encryptedDatabaseName). GetCollection<Patient>(encryptedCollectionName); encryptedCollection.InsertOne(patient);
创建描述患者个人信息的示例文档。使用加密的客户端将其插入到 patients
集合中,如以下示例所示:
patientDocument := &PatientDocument{ PatientName: "Jon Doe", PatientID: 12345678, PatientRecord: PatientRecord{ SSN: "987-65-4320", Billing: PaymentInfo{ Type: "Visa", Number: "4111111111111111", }, BillAmount: 1500, }, } coll := encryptedClient.Database(encryptedDatabaseName).Collection(encryptedCollectionName) _, err = coll.InsertOne(context.TODO(), patientDocument) if err != nil { panic(fmt.Sprintf("Unable to insert the patientDocument: %s", err)) }
本教程使用 POJO 作为数据模型来表示文档结构。 要将应用程序设立为使用 POJO,请添加以下代码:
CodecProvider pojoCodecProvider = PojoCodecProvider.builder().automatic(true).build(); CodecRegistry pojoCodecRegistry = fromRegistries(getDefaultCodecRegistry(), fromProviders(pojoCodecProvider));
要学习;了解有关Java POJO 的更多信息,请参阅 维基百科文章“普通旧Java对象”。
本教程使用以下 POJO:
Patient
PatientRecord
PatientBilling
将这些 POJO 类添加到您的应用程序中。 然后,创建描述患者个人信息的Patient
实例。 使用加密客户端将其插入到patients
集合中,如以下示例所示:
MongoDatabase encryptedDb = encryptedClient.getDatabase(encryptedDatabaseName).withCodecRegistry(pojoCodecRegistry); MongoCollection<Patient> collection = encryptedDb.getCollection(encryptedCollectionName, Patient.class); PatientBilling patientBilling = new PatientBilling("Visa", "4111111111111111"); PatientRecord patientRecord = new PatientRecord("987-65-4320", patientBilling, 1500); Patient patientDocument = new Patient("Jon Doe", patientRecord); InsertOneResult result = collection.insertOne(patientDocument);
创建描述患者个人信息的示例文档。使用加密的客户端将其插入到 patients
集合中,如以下示例所示:
const patientDocument = { patientName: "Jon Doe", patientId: 12345678, patientRecord: { ssn: "987-65-4320", billing: { type: "Visa", number: "4111111111111111", }, billAmount: 1500, }, }; const encryptedCollection = encryptedClient .db(encryptedDatabaseName) .collection(encryptedCollectionName); const result = await encryptedCollection.insertOne(patientDocument);
创建描述患者个人信息的示例文档。使用加密的客户端将其插入到 patients
集合中,如以下示例所示:
patient_document = { "patientName": "Jon Doe", "patientId": 12345678, "patientRecord": { "ssn": "987-65-4320", "billing": { "type": "Visa", "number": "4111111111111111", }, "billAmount": 1500, }, } encrypted_collection = encrypted_client[encrypted_database_name][encrypted_collection_name] result = encrypted_collection.insert_one(patient_document)
加密字段查询
下面的代码示例对加密字段执行查找查询,并打印解密后的数据:
const findResult = await encryptedCollection.findOne({ "patientRecord.ssn": "987-65-4320", }); console.log(findResult);
var ssnFilter = Builders<Patient>.Filter.Eq("patientRecord.ssn", patient.PatientRecord.Ssn); var findResult = await encryptedCollection.Find(ssnFilter).ToCursorAsync(); Console.WriteLine(findResult.FirstOrDefault().ToJson());
var findResult PatientDocument err = coll.FindOne( context.TODO(), bson.M{"patientRecord.ssn": "987-65-4320"}, ).Decode(&findResult)
Patient findResult = collection.find( new BsonDocument() .append("patientRecord.ssn", new BsonString("987-65-4320"))) .first(); System.out.println(findResult);
const findResult = await encryptedCollection.findOne({ "patientRecord.ssn": "987-65-4320", }); console.log(findResult);
find_result = encrypted_collection.find_one({ "patientRecord.ssn": "987-65-4320" }) print(find_result)
上述代码示例的输出应类似于以下内容:
{ "_id": { "$oid": "648b384a722cb9b8392df76a" }, "name": "Jon Doe", "record": { "ssn": "987-65-4320", "billing": { "type": "Visa", "number": "4111111111111111" }, "billAmount": 1500 }, "__safeContent__": [ { "$binary": { "base64": "L1NsYItk0Sg+oL66DBj6IYHbX7tveANQyrU2cvMzD9Y=", "subType": "00" } } ] }
警告
不要修改 __safeContent__ 字段
__safeContent__
字段对于 Queryable Encryption 至关重要。请勿修改此字段的内容。
了解详情
要查看有关使用远程KMS进行面向生产环境的Queryable Encryption的教程,请参阅教程。
如需了解 Queryable Encryption 的工作原理,请参阅基础知识。
如需详细了解本指南中提到的主题,请参阅以下链接:
有关 Queryable Encryption 组件的更多信息,请参阅参考页面。
在加密密钥和密钥保管库页面上了解客户主密钥和数据加密密钥的工作原理。
在 KMS 提供商页面上查看 KMS 提供商如何管理您的可查询加密密钥。