You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何添加含{cipher}加密属性的外部PropertySource并实现自动解密?

如何解密外部属性源中的{cipher}加密属性

一、Spring能解密application-*.yml中{cipher}属性的原因

Spring Boot(通常配合Spring Cloud Config)对内置配置文件的解密是在属性加载阶段自动完成的:

  • 对于application-*.yml这类文件,Spring会通过专用加载器(如YamlPropertySourceLoader)读取,这些加载器集成了解密逻辑。
  • 加载时会自动识别带{cipher}前缀的属性值,调用对应解密组件(如CipherResourceYamlEncryptor)完成解密,再将解密后的值注入环境。整个流程是配置加载的固有环节,无需额外操作。

二、让外部PropertiesPropertySource属性自动解密的方案

你的问题出在直接将未解密的Properties对象添加到环境中,跳过了Spring的解密流程。以下两种方案可以解决:

方案1:手动调用解密器预处理Properties

在添加属性源前,先手动处理Properties中的加密属性。需要先初始化解密器(依赖环境中的加密配置,如密钥),再遍历属性完成解密:

import org.springframework.cloud.context.encrypt.EncryptorFactoryBean;
import org.springframework.core.env.Environment;
import org.springframework.security.crypto.encrypt.TextEncryptor;
import java.util.Properties;
import java.util.Set;

public class PropertyDecryptor {
    public static Properties decrypt(Properties rawProps, Environment env) {
        TextEncryptor encryptor = createTextEncryptor(env);
        Properties decryptedProps = new Properties();
        Set<String> keys = rawProps.stringPropertyNames();
        
        for (String key : keys) {
            String value = rawProps.getProperty(key);
            if (value != null && value.startsWith("{cipher}")) {
                String encryptedContent = value.substring("{cipher}".length());
                decryptedProps.setProperty(key, encryptor.decrypt(encryptedContent));
            } else {
                decryptedProps.setProperty(key, value);
            }
        }
        return decryptedProps;
    }

    private static TextEncryptor createTextEncryptor(Environment env) {
        EncryptorFactoryBean factory = new EncryptorFactoryBean();
        factory.setEnvironment(env);
        try {
            factory.afterPropertiesSet();
            return factory.getObject();
        } catch (Exception e) {
            throw new RuntimeException("Failed to initialize decryptor", e);
        }
    }
}

在监听器中使用:

class MyApplicationContextListener implements ApplicationListener<ApplicationContextInitializedEvent> {

    @Override
    public void onApplicationEvent(ApplicationContextInitializedEvent event) {
        ConfigurableEnvironment env = event.getApplicationContext().getEnvironment();
        Properties decryptedProps = PropertyDecryptor.decrypt(properties, env);
        env.getPropertySources().addLast(new PropertiesPropertySource(sourceName, decryptedProps));
    }
}

方案2:用EncryptablePropertySource包装原属性源

如果是Spring Cloud环境,直接用EncryptablePropertySource包装你的属性源,它会自动处理解密逻辑:

import org.springframework.cloud.context.environment.EncryptablePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;

class MyApplicationContextListener implements ApplicationListener<ApplicationContextInitializedEvent> {

    @Override
    public void onApplicationEvent(ApplicationContextInitializedEvent event) {
        ConfigurableEnvironment env = event.getApplicationContext().getEnvironment();
        PropertiesPropertySource rawSource = new PropertiesPropertySource(sourceName, properties);
        EncryptablePropertySource encryptableSource = new EncryptablePropertySource(rawSource.getName(), rawSource.getSource(), env);
        env.getPropertySources().addLast(encryptableSource);
    }
}

注意事项

  • 确保加密配置(如encrypt.key)在添加外部属性源前已加载(比如来自application.yml),否则解密器无法初始化。
  • 若使用自定义加密逻辑,需替换对应的解密实现,而非依赖Spring Cloud默认组件。

内容的提问来源于stack exchange,提问作者Andy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 11:09:59