加密 (CSFLE)
客户端加密是在数据发送到 MongoDB 之前在您的应用程序中对数据进行加密的功能。我们建议您熟悉这些概念,最好是从 MongoDB 文档 中学习更多关于其功能和限制的信息,然后再继续通过 Spring Data 应用加密。
确保设置驱动程序的 |
自动加密
有关定义包含加密信息的 JSON 架构的更多信息,请参阅 JSON 架构 部分。
为了使用 MongoJsonSchema
,它需要与 AutoEncryptionSettings
结合使用,这可以通过例如 MongoClientSettingsBuilderCustomizer
来完成。
@Bean
MongoClientSettingsBuilderCustomizer customizer(MappingContext mappingContext) {
return (builder) -> {
// ... keyVaultCollection, kmsProvider, ...
MongoJsonSchemaCreator schemaCreator = MongoJsonSchemaCreator.create(mappingContext);
MongoJsonSchema patientSchema = schemaCreator
.filter(MongoJsonSchemaCreator.encryptedOnly())
.createSchemaFor(Patient.class);
AutoEncryptionSettings autoEncryptionSettings = AutoEncryptionSettings.builder()
.keyVaultNamespace(keyVaultCollection)
.kmsProviders(kmsProviders)
.extraOptions(extraOpts)
.schemaMap(Collections.singletonMap("db.patient", patientSchema.schemaDocument().toBsonDocument()))
.build();
builder.autoEncryptionSettings(autoEncryptionSettings);
};
}
显式加密
显式加密使用 MongoDB 驱动程序的加密库 (org.mongodb:mongodb-crypt
) 来执行加密和解密任务。@ExplicitEncrypted
注解是用于 JSON Schema 创建 的 @Encrypted
注解和 属性转换器 的组合。换句话说,@ExplicitEncrypted
使用现有的构建块将它们组合起来,以简化显式加密支持。
使用
|
客户端字段级加密允许您在确定性算法和随机算法之间进行选择。根据 所选算法,可能支持 不同的操作。要选择特定算法,请使用 @ExplicitEncrypted(algorithm)
,请参见 EncryptionAlgorithms
获取算法常量。有关算法及其用法的更多信息,请阅读 加密类型 手册。
要执行实际加密,我们需要一个数据加密密钥 (DEK)。有关如何设置密钥管理和创建数据加密密钥的更多信息,请参阅 MongoDB 文档。DEK 可以通过其 id
或定义的备用名称直接引用。@EncryptedField
注解仅允许通过备用名称引用 DEK。可以向任何 DEK 提供一个 EncryptionKeyResolver
,这将在后面讨论。
@EncryptedField(algorithm=…, altKeyName = "secret-key") (1)
String ssn;
@EncryptedField(algorithm=…, altKeyName = "/name") (2)
String ssn;
1 | 使用以备用名称 secret-key 存储的 DEK。 |
2 | 使用字段引用,该引用将读取实际字段值并将其用于密钥查找。始终需要完整的文档才能执行保存操作。字段不能在查询/聚合中使用。 |
默认情况下,@ExplicitEncrypted(value=…)
属性引用 MongoEncryptionConverter
。可以通过提供相应的类型引用来更改默认实现并将其替换为任何 PropertyValueConverter
实现。要了解有关自定义 PropertyValueConverters
和所需配置的更多信息,请参阅 属性转换器 - 映射特定字段 部分。
MongoEncryptionConverter 设置
MongoEncryptionConverter
的转换器设置需要几个步骤,因为涉及多个组件。Bean 设置包括以下内容:
-
ClientEncryption
引擎 -
使用
ClientEncryption
和EncryptionKeyResolver
配置的MongoEncryptionConverter
实例。 -
使用已注册的
MongoEncryptionConverter
Bean 的PropertyValueConverterFactory
。
使用带注释的密钥解析的副作用是,@ExplicitEncrypted
注释不需要指定备用密钥名称。EncryptionKeyResolver
使用 EncryptionContext
提供对属性的访问,从而允许动态 DEK 解析。
class Config extends AbstractMongoClientConfiguration {
@Autowired ApplicationContext appContext;
@Bean
ClientEncryption clientEncryption() { (1)
ClientEncryptionSettings encryptionSettings = ClientEncryptionSettings.builder();
// …
return ClientEncryptions.create(encryptionSettings);
}
@Bean
MongoEncryptionConverter encryptingConverter(ClientEncryption clientEncryption) {
Encryption<BsonValue, BsonBinary> encryption = MongoClientEncryption.just(clientEncryption);
EncryptionKeyResolver keyResolver = EncryptionKeyResolver.annotated((ctx) -> …); (2)
return new MongoEncryptionConverter(encryption, keyResolver); (3)
}
@Override
protected void configureConverters(MongoConverterConfigurationAdapter adapter) {
adapter
.registerPropertyValueConverterFactory(PropertyValueConverterFactory.beanFactoryAware(appContext)); (4)
}
}
1 | 使用 com.mongodb.client.vault.ClientEncryption 设置 Encryption 引擎。该实例是有状态的,必须在使用后关闭。Spring 会处理此操作,因为 ClientEncryption 是 Closeable 。 |
2 | 设置基于注释的 EncryptionKeyResolver 以从注释中确定 EncryptionKey 。 |
3 | 创建 MongoEncryptionConverter 。 |
4 | 为 BeanFactory 中的 PropertyValueConverter 查找启用。 |