对于最新的稳定版本,请使用 Spring Data MongoDB 4.4.0spring-doc.cadn.net.cn

加密 (CSFLE)

Client Side Encryption 是一项功能,可在将应用程序中的数据发送到 MongoDB 之前对其进行加密。 我们建议您熟悉这些概念,最好先从 MongoDB 文档 中了解有关其功能和限制的更多信息,然后再继续通过 Spring Data 应用加密。spring-doc.cadn.net.cn

确保设置驱动程序com.mongodb.AutoEncryptionSettings以使用客户端加密。 MongoDB 不支持对所有字段类型进行加密。 特定数据类型需要确定性加密以保留相等比较功能。spring-doc.cadn.net.cn

自动加密

MongoDB 使用 MongoDB 驱动程序及其自动加密功能支持开箱即用的客户端字段级加密。 自动加密需要一个 JSON 架构,该架构允许执行加密的读取和写入作,而无需提供显式的 en-/decryption 步骤。spring-doc.cadn.net.cn

请参阅 JSON 架构 有关定义包含加密信息的 JSON 架构的更多信息。spring-doc.cadn.net.cn

要使用MongoJsonSchema它需要与AutoEncryptionSettings这可以做到,例如。通过MongoClientSettingsBuilderCustomizer.spring-doc.cadn.net.cn

@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) 执行加密和解密任务。 这@ExplicitEncryptedannotation 是@Encrypted用于 JSON 架构创建和属性转换器的注释。 换句话说,@ExplicitEncrypted使用现有构建块将它们组合在一起,以实现简化的显式加密支持。spring-doc.cadn.net.cn

注释为@ExplicitEncrypted始终作为整体加密。 请考虑以下示例:spring-doc.cadn.net.cn

@ExplicitEncrypted(…)
String simpleValue;        (1)

@ExplicitEncrypted(…)
Address address;           (2)

@ExplicitEncrypted(…)
List<...> list;            (3)

@ExplicitEncrypted(…)
Map<..., ...> mapOfString; (4)
1 加密简单类型的值,例如String如果不是null.
2 加密整个Addressobject 及其所有嵌套字段作为Document. 要仅加密Address喜欢Address#streetstreet字段中Address需要注释@ExplicitEncrypted.
3 Collection-like 字段被加密为单个值,而不是按条目加密。
4 Map-like 字段加密为单个值,而不是键/值条目。

Client-Side Field Level Encryption 允许您在确定性算法和随机算法之间进行选择。根据所选的算法,可能支持不同的作。 要选择某种算法,请使用@ExplicitEncrypted(algorithm)EncryptionAlgorithms对于算法常量。 请阅读 加密类型 手册 以了解有关算法及其用法的更多信息。spring-doc.cadn.net.cn

要执行实际加密,我们需要数据加密密钥 (DEK)。 有关如何设置密钥管理和创建数据加密密钥的更多信息,请参阅 MongoDB 文档。 DEK 可以通过其id或定义的替代名称。 这@EncryptedFieldannotation 只允许通过替代名称引用 DEK。 可以提供EncryptionKeyResolver,这将在后面讨论,适用于任何 DEK。spring-doc.cadn.net.cn

示例 1.引用数据加密密钥
@EncryptedField(algorithm=…, altKeyName = "secret-key") (1)
String ssn;
@EncryptedField(algorithm=…, altKeyName = "/name")      (2)
String ssn;
1 使用与备用名称一起存储的 DEKsecret-key.
2 使用字段引用,该引用将读取实际字段值并将其用于键查找。 始终要求存在完整的文档才能进行保存作。 字段不能用于查询/聚合。

默认情况下,@ExplicitEncrypted(value=…)属性引用MongoEncryptionConverter. 可以更改默认实现并将其与任何PropertyValueConverterimplementation 的 intent 的 intent 来提供相应的类型引用。 了解有关自定义的更多信息PropertyValueConverters和所需的配置,请参阅 Property Converters - 映射特定字段 部分。spring-doc.cadn.net.cn

MongoEncryptionConverter 设置

的转换器设置MongoEncryptionConverter需要几个步骤,因为涉及多个组件。 Bean 设置包括以下内容:spring-doc.cadn.net.cn

  1. ClientEncryption发动机spring-doc.cadn.net.cn

  2. 一个MongoEncryptionConverter实例配置了ClientEncryption以及EncryptionKeyResolver.spring-doc.cadn.net.cn

  3. 一个PropertyValueConverterFactory使用已注册的MongoEncryptionConverter豆。spring-doc.cadn.net.cn

使用带注释的键解析的副作用是@ExplicitEncryptedannotation 不需要指定 alt 键名称。 这EncryptionKeyResolver使用EncryptionContext提供对允许动态 DEK 解析的属性的访问。spring-doc.cadn.net.cn

示例 2.MongoEncryptionConverter 配置示例
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 设置Encryptionengine 使用com.mongodb.client.vault.ClientEncryption. 该实例是有状态的,使用后必须关闭。 Spring 会处理这个问题,因为ClientEncryptionCloseable.
2 设置基于注释EncryptionKeyResolver要确定EncryptionKeyfrom annotations 中。
3 创建MongoEncryptionConverter.
4 Enable 的PropertyValueConverterBeanFactory.