在很多开发场景中SpringBoot应用的数据库、Redis缓存、消息队列、第三方服务等账号密码信息直接明文存储在配置文件中,没有进行相应的加密处理。正常情况下我们应该将这些信息进行脱敏,避免泄露。
Jasypt可以为Springboot加密的信息很多,主要有System Property 系统变量、Envirnment Property 环境变量、Command Line argument 命令行参数、properties 应用配置文件、Yaml应用配置文件、other custom property sources 其它配置文件等.
第一步、添加POM依赖
Jasypt整合到Springboot是另一个开源项目jasypt-spring-boot,主要有三种整合方式:
方式一:使用jasypt-spring-boot-starter依赖,并在启动类@SpringBootApplication或@EnableAutoConfiguration注解,对所有配置信息都进行加密解密
<dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>2.1.1</version></dependency>
方式二:使用jasypt-spring-boot依赖,并在配置类上使用@Configuration和@EnableEncryptableProperties注解,对所有配置信息都进行加密解密
//POM.xml中引入依赖<dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot</artifactId> <version>2.1.1</version></dependency>//配置类中使用@Configuration和@EnableEncryptableProperties注解@Configuration@EnableEncryptablePropertiespublic class EncrypConfig { }
方式三:使用jasypt-spring-boot依赖,并在配置类上使用@Configuration和@EnableEncryptableProperties注解,对特定配置信息都进行加密解密
//POM.xml中引入依赖<dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot</artifactId> <version>2.1.1</version></dependency>//配置类中使用@Configuration和@EnableEncryptableProperties注解@Configuration@EncryptablePropertySource(name = "EncryptedProperties", value = "classpath:encryptedperties")public class EncrypConfig { }
第二步、添加密钥
在Springboot设置jasypt的密钥有配置文件、自定义配置类和启动参数进行设置三种方式。
方式一:在application.yml配置文件中设置密钥。缺点是安全性低、容易泄露
jasypt: encryptor: password: MYPASSWORD
方式二:创建自定义加密配置类,在java代码中设置密钥。缺点是安全性相对较低、反编译后容易泄露
@Configurationpublic class EncryptorCfg { @Bean( name = "myEncryptorBean" ) public StringEncryptor jasyptStringEncryptor() { PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor(); SimpleStringPBEConfig config = new SimpleStringPBEConfig(); config.setPassword("MYPASSWORD"); 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的名字name默认是jasyptStringEncryptor,若指定为其他名称则需要在Spring Boot的application.yml配置文件中来指定bean的名字,如
jasypt: encryptor: bean: myEncryptorBean
方式三:在启动时传入命令行参数或环境变量、配置文件中使用系统环境变量。优点是相对安全,不容易泄露。
//启动jar时传入参数:--jasypt.encryptor.password=MYPASSWORDjava -jar yourproject.jar --jasypt.encryptor.password=MYPASSWORD//启动jar时传入环境变量:-Djasypt.encryptor.password=MYPASSWORDjava -Djasypt.encryptor.password=MYPASSWORD -jar yourproject.jar//服务器系统环境变量中配置变量JASYPT_ENCRYPTOR_PASSWORD = MYPASSWORD,//并在application.yml中配置引用环境变量jasypt.encryptor.password=${JASYPT_ENCRYPTOR_PASSWORD:}
第三步、将需要加密的明文生成密文
注入StringEncryptor并通过encrypt()方法进行加密,也可通过decrypt()解密。
@SpringBootTestpublic class MyTest { @Autowired private StringEncryptor encryptor; @Test public void testDemo() { //加密 String url = encryptor.encrypt("jdbc:p6spy:oracle:thin:@localhost:1521/oracle"); String username = encryptor.encrypt("admin"); String password = encryptor.encrypt("123456"); String driver = encryptor.encrypt("com.p6spy.engine.spy.P6SpyDriver"); System.out.println("url加密:"+url); System.out.println("username加密:"+username); System.out.println("password加密:"+password); System.out.println("driver加密:"+driver); //解密 String url1 = encryptor.decrypt(url); String username1 = encryptor.decrypt(username); String password1 = encryptor.decrypt(password); String driver1 = encryptor.decrypt(driver); System.out.println("url解密:"+url1); System.out.println("username解密:"+username1); System.out.println("password解密:"+password1); System.out.println("driver解密:"+driver1); }}
第四步、将生成的密文配置到相应的配置文件中,如在application.yml中配置数据库加密后的数据库链接信息
spring: datasource: url: ENC(hdsW9ocz1VJRwG3qfvdp9BPvEYg0SN6uPzr/YEhkFkqwbRC2PXyk0dUq7ytib8zgr6RjZG2eNbgSfFgx1CL8cbEBQ2zam5HxvhUSpNVzZ6U=) username: ENC(IhWd5YSDfuuh4/+d3oXGeJq39tcGuhV0BvJOyyzwHw//0DSdmQTPNd1nrOiQSb61) password: ENC(1NHGNYCblMkj3BqjnVRlrhAIRFRfplh1oPM4LS7S36Lr4cVov2iqTL9Ehc6tBbwQ)
说明:默认使用的是ENC()对加密后的密文进行包裹,我们也可以在application.yml中进行指定,如MM()
jasypt: encryptor: property: prefix: 'MM(' suffix: ')'