在項目中一般會將數據庫,Redis等一些連接配置信息放在Properties(屬性配置)文件中,Spring配置文件中通過context:property-placeholder 引入,需要屬性的地方使用${屬性key}的方式。在SpringBoot項目中,這些配置信息則在yml文件中。出於安全的考慮,一般會將這些信息進行加密
其實加密的思路就是:自定義加密規則,加密明文得到密文,使用密文替換明文,繼承placeholder,在自定義的placeholder中進行解密,Spring配置文件使用自定義的placeholder引入配置文件。這些操作完全可以自己去實現而不用借助第三方,但是使用jasypt更加簡化這些步驟
jasypt
我這里采用PBEWithMD5AndDES加密方法,每次運行得到的密文都是不一樣的,但是可以通過這些密文解密得到唯一的明文,這種加密方法也屬於可逆加密的一種,也只有可逆加密方法才適合對配置信息進行加密,畢竟涉及到加密和解密雙向操作
jasypt與Spring整合
引入依賴
<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt</artifactId>
<version>1.9.3</version>
</dependency>
<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt-spring31</artifactId>
<version>1.9.3</version>
</dependency>
加密明文得到密文
直接通過jasypt的api進行加密
public static void main(String[] args) {
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
// 設置密鑰
config.setPassword("password");
// 設置加密方法
config.setAlgorithm("PBEWithMD5AndDES");
encryptor.setConfig(config);
// 加密
String encryptStr = encryptor.encrypt("123456");
System.out.println(encryptStr);
// 解密
// System.out.println(encryptor.decrypt(encryptStr));
}
加密和解密必須使用同一個密鑰
通過一個main方法直接得到需要的密文,接下來在屬性文件中進行替換
使用密文替換明文
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql:///maven
jdbc.user=root
jdbc.password=ENC(/a2d+QFXZXOl79sTxozVEw==)
這里只針對password進行加密,實際上所有的屬性都可以加密,但是必須使用ENC(密文)的格式,這是jasypt規定的
配置jasypt
配置jasypt有兩種方式:通過XML,通過配置類。
XML方式
<!--配置加密方式及密鑰-->
<bean id="environmentVariablesConfiguration" class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
<!--加密方式-->
<property name="algorithm" value="PBEWithMD5AndDES"/>
<!--密鑰-->
<property name="password" value="MYPASSWORD"/>
</bean>
<!--配置加密器,將用於解密-->
<bean id="configurationEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
<property name="config" ref="environmentVariablesConfiguration"/>
</bean>
<!-- 使用EncryptablePropertyPlaceholderConfigurer引入屬性文件 不再使用context:property-placeholder-->
<bean id="placeholderConfig" class="org.jasypt.spring31.properties.EncryptablePropertyPlaceholderConfigurer">
<constructor-arg ref="configurationEncryptor"/>
<property name="locations">
<list>
<!--根據實際情況替換成項目屬性文件位置-->
<value>classpath:/properties/jdbc.properties</value>
<value>file:D://properties//jdbc.properties</value>
</list>
</property>
</bean>
配置類方式
package com.config;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig;
import org.jasypt.spring31.properties.EncryptablePropertyPlaceholderConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
@Configuration
public class EncryPropertiesConfig {
/**
* 配置加密方式及密鑰
* @return
*/
@Bean
public EnvironmentStringPBEConfig getEnvironmentStringPBEConfig() {
EnvironmentStringPBEConfig config = new EnvironmentStringPBEConfig();
// 設置加密方式
config.setAlgorithm("PBEWithMD5AndDES");
// 設置密鑰
config.setPassword("MYPASSWORD");
return config;
}
/**
* 配置加密器,將用於解密
* @return
*/
@Bean
public StandardPBEStringEncryptor getStandardPBEStringEncryptor() {
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
encryptor.setConfig(getEnvironmentStringPBEConfig());
return encryptor;
}
/**
* 引入屬性文件
* @return
*/
@Bean
public EncryptablePropertyPlaceholderConfigurer getEncryptablePropertyPlaceholderConfigurer() {
EncryptablePropertyPlaceholderConfigurer placeholderConfigurer = new EncryptablePropertyPlaceholderConfigurer(getStandardPBEStringEncryptor());
placeholderConfigurer.setLocation(new ClassPathResource("/properties/jdbc.properties"));
placeholderConfigurer.setLocation(new FileSystemResource("D://properties//jdbc.properties"));
return placeholderConfigurer;
}
}
將這個配置所在的包配置在context:component-scan掃描范圍下,這樣就可以了
<context:component-scan base-package="com.lynu;com.config"></context:component-scan>
jasypt與SpringBoot整合
引入依賴
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
加密明文得到密文
同Spring整合的方法一樣,寫一個main方法調用jasypt的api,這里不在復述
使用密文替換明文
# 數據源配置
datasource:
url: jdbc:mysql:///maven
driver-class-name: com.mysql.jdbc.Driver
username: root
password: ENC(/a2d+QFXZXOl79sTxozVEw==)
這里同樣需要使用ENC(密文)的格式
配置jasypt
jasypt:
encryptor:
algorithm: PBEWithMD5AndDES
password: MYPASSWORD
其他加密方案
Spring中使用jasypt,實際上就是替換placeholder進行的,如果項目中的某些配置,沒有使用 placeholder + ${} 的方法,又該如何配置呢?
- 自定義加解密方法
- 加密明文得到密文,使用密文替換,只不過不用ENC()的格式了,因為是我們自定義的方案
- 將XML中的配置改為Java類的配置方法,在配置類中解密
我實現過Quartz
和Logback
的,二者都有操作數據庫的連接信息(Quartz將定時配置在數據庫,Logback往數據庫中insert日志)
Quartz
參考的是 【Quartz】解密properties配置文件中的賬號密碼
Logback
我通過繼承DataSourceConnectionSource
,重寫方法getConnection()
方法,在這個方法中對密碼進行解密
更多jasypt
加密方法與使用技巧,可以參考jasypt官網 以及 jasypt-spring-boot的github地址