SpringBoot配置文件加密

Lou.Chen
大约 3 分钟

SpringBoot配置文件加密

​ 当我们在发布项目部署的时候,是否会发现配置文件被暴露在环境中,且配置文件里面的密码为明文,这样非常不安全。

例如:

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    username: root
    #明文 不安全
    password: 123456
  redis:
    database: 0
    #明文 不安全
    password: 123456
    port: 6379

这是我们需要一个加密组件jasypt-spring-boot

一、引入组件依赖

<!--配置文件加密-->
<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>3.0.2</version>
</dependency>

二、加入加密密钥(盐)

我们在application.yaml中加入以下配置

jasypt:
  encryptor:
    password: louchen

可以理解为jasypt会使用这个自定义加密密钥,对配置文件里的重要项进行加密。

三、加密测试

使主配置类实现CommandLineRunner接口,在启动程序时输出指定内容

@SpringBootApplication
public class VrhApplication implements CommandLineRunner {

    @Autowired
    private ApplicationContext appCtx
    @Autowired
    private StringEncryptor stringEncryptor;

    public static void main(String[] args) {
        SpringApplication.run(VrhApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {

        //读取配置文件
        Environment environment = appCtx.getBean(Environment.class);

        // 首先获取配置文件里的原始明文信息
        String mysqlOriginPswd = environment.getProperty("spring.datasource.password");
        String redisOriginPswd = environment.getProperty("spring.redis.password");

        String mysqlencrypt = encrypt(mysqlOriginPswd);
        System.out.println("加密:"+mysqlOriginPswd+">>>>>密文:"+ mysqlencrypt);
        System.out.println("解密:>>>>>明文:"+decrypt(mysqlencrypt));
        System.out.println("----------------");
        String redisencrypt = encrypt(redisOriginPswd);
        System.out.println("加密:"+mysqlOriginPswd+">>>>>密文:"+ redisencrypt);
       System.out.println("解密:>>>>>明文:"+decrypt(redisencrypt));
    }

    /**
     * 加密
     * @param orginPws 明文
     * @return
     */
    private String encrypt(String orginPws){
        return stringEncryptor.encrypt(orginPws);
    }

    /**
     *解密
     * @param depryptPwd 密文
     * @return
     */
    private String decrypt(String depryptPwd){
        return stringEncryptor.decrypt(depryptPwd);
    }
}

四、修改配置文件替换明文

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    username: root
    #替换的密文
    password: ENC(HRdQoZQEkagFOmHEFP3+FAPHasQJoxHmgezz559eMnBhGj2W1nj)
  redis:
    database: 0
    #替换的密文
    password: ENC(YJvMXx9L4h3dr3gPFr+lm1wA1WGTordEGSDhymm8YtnN43yReAp5udGy662)
    port: 6379

这里我们可以看出。在代码中使用时,jasypt-spring-boot组件会自动将ENC()语法包裹的配置项加密字段自动解密,数据得以还原。

五、加密密钥为什么在ENC()中,可以更改吗?

自定义加密前缀
jasypt:
  encryptor:
    property:
      prefix: lc(
      suffix: )

再次修改application.yaml文件

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    username: root
    #替换的密文
    password: lc(HRdQoZQEkagFOmHEFP3+FAPHasQJoxHmgezz559eMnBhGj2W1nj)
  redis:
    database: 0
    #替换的密文
    password: lc(YJvMXx9L4h3dr3gPFr+lm1wA1WGTordEGSDhymm8YtnN43yReAp5udGy662)
    port: 6379

六、担心jasypt.encryptor.password设置的盐被泄露?

我们的加密密钥放在配置application.yaml中难免有些不安全,这时我们可以使用自定义加密器

使用自定义加密器

我们自自定义一个加密器配置类即可

@Configuration
public class ConfigEncryptBean {

    @Bean
    public StringEncryptor lcEncryptBean() {
        PooledPBEStringEncryptor encryptor=new PooledPBEStringEncryptor();

        SimpleStringPBEConfig config=new SimpleStringPBEConfig();
//        设置盐
        config.setPassword("louchen");
//        设置加密算法
        config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
//        迭代次数
        config.setKeyObtentionIterations("1000");
//        池的大小
        config.setPoolSize("1");
        config.setProviderName("SunJCE");
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
        config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
        config.setStringOutputType("base64");
        encryptor.setConfig(config);
        return encryptor;
    }
}

注意:上面bean的名字默认为方法名。我们可以使用@Bean注解更改bean的名称·

更改application.yaml

# 加密配置
jasypt:
  encryptor:
    property:
      prefix: lc(
      suffix: )
    bean: lcEncryptBean

这是我们的密钥盐就在bean中,比较安全的防止别人获取盐

七、其他密钥设置方式

方式一:直接作为程序启动时的命令行参数来带入

java -jar yourproject.jar --jasypt.encryptor.password=louchen

方式二:直接作为程序启动时的应用环境变量来带入

java -Djasypt.encryptor.password=louchen -jar yourproject.jar

方式三:甚至可以作为系统环境变量的方式来带入

比方说,我们提前设置好系统环境变量JASYPT_ENCRYPTOR_PASSWORD = louchen,则直接在Spring Boot的项目配置文件中做如下配置即可:

jasypt.encryptor.password=${JASYPT_ENCRYPTOR_PASSWORD:}

这时候也会安全得多。