如果Spring boot
的配置文件大多是明文 ,这样是不安全的;
如果Mysql数据库的账号密码都是明文,安全性就降低了,就像是在裸奔一样,所以有必要对相关比较隐秘的数据进行加密,这样的话相对安全性高一点;
这里我们采用jasypt
对数据库的连接、账号和名称进行加密处理;
jasypt
加密依赖
<dependency>
<groupId>com.github.ulisesbocchiogroupId>
<artifactId>jasypt-spring-boot-starterartifactId>
<version>2.1.0version>
dependency>
jasypt中加密方法的类有两个:BasicTextEncryptor 和 StrongTextEncryptor
public final class BasicTextEncryptor implements TextEncryptor {
private final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
public BasicTextEncryptor() {
this.encryptor.setAlgorithm("PBEWithMD5AndDES");
}
public void setPassword(String password) {
this.encryptor.setPassword(password);
}
public void setPasswordCharArray(char[] password) {
this.encryptor.setPasswordCharArray(password);
}
public String encrypt(String message) {
return this.encryptor.encrypt(message);
}
public String decrypt(String encryptedMessage) {
return this.encryptor.decrypt(encryptedMessage);
}
}
BasicTextEncryptor 对应的加密方式是 PBEWithMD5AndDES(默认方式)
public final class StrongTextEncryptor implements TextEncryptor {
private final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
public StrongTextEncryptor() {
this.encryptor.setAlgorithm("PBEWithMD5AndTripleDES");
}
public void setPassword(String password) {
this.encryptor.setPassword(password);
}
public void setPasswordCharArray(char[] password) {
this.encryptor.setPasswordCharArray(password);
}
public String encrypt(String message) {
return this.encryptor.encrypt(message);
}
public String decrypt(String encryptedMessage) {
return this.encryptor.decrypt(encryptedMessage);
}
}
StrongTextEncryptor对应的加密方式是 PBEWithMD5AndTripleDES
假设我们的配置文件如下:
src/main/resources/application.yml
server:
port: 9002
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username: admin
password: test2011
#jasypt加密的密匙
jasypt:
encryptor:
# 加密所需的salt(盐)
# 加密方式和算法一定要对应一致
# BasicTextEncryptor 对应加密方式:PBEWithMD5AndDES,StrongTextEncryptor 对应加密方式: PBEWithMD5AndTripleDES
# 部署时配置salt(盐)值 java -jar -Djasypt.encryptor.password=1qaz2wsx3edc -Djasypt.encryptor.algorithm=PBEWithMD5AndDES xxx.jar
# 或者在服务器的环境变量里配置,进一步提高安全性
# 打开/etc/profile文件 vim /etc/profile
# 文件末尾插入 export JASYPT_PASSWORD = SALT
# 文件末尾插入 export JASYPT_ALGORITHM = ALGORITHM
# 编译 source /etc/profile
# 运行 java -jar -Djasypt.encryptor.password=${JASYPT_PASSWORD} -Djasypt.encryptor.algorithm=${JASYPT_ALGORITHM} xxx.jar
password: 1qaz2wsx3edc
# 默认加密方式PBEWithMD5AndDES,可以更改为PBEWithMD5AndTripleDES
algorithm: PBEWithMD5AndTripleDES
下面我们写一个测试类进行加密: com.scaffold.test.ScaffoldApplicationTests
package com.scaffold.test;
import com.scaffold.test.constants.BaseApplication;
import lombok.extern.slf4j.Slf4j;
import org.jasypt.util.text.BasicTextEncryptor;
import org.jasypt.util.text.StrongTextEncryptor;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ScaffoldApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ScaffoldApplicationTests {
@Autowired
private BaseApplication baseApplication;
/**
* 基础加密
*/
@Test
public void getPass() {
BasicTextEncryptor basicTextEncryptor = new BasicTextEncryptor();
//加密所需的salt(盐)
basicTextEncryptor.setPassword("1qaz2wsx3edc");
// 加密数据库相关连接数据
String url = basicTextEncryptor.encrypt(baseApplication.getDataSourceUrl());
String name = basicTextEncryptor.encrypt(baseApplication.getDataSourceUserName());
String password = basicTextEncryptor.encrypt(baseApplication.getDataSourcePassword());
log.info("---url---");
log.info(url);
log.info("---name---");
log.info(name);
log.info("---password---");
log.info(password);
}
/**
* 强加密
*/
@Test
public void getStrongPass() {
StrongTextEncryptor strongTextEncryptor = new StrongTextEncryptor();
//加密所需的salt(盐)
strongTextEncryptor.setPassword("1qaz2wsx3edc");
// 加密数据库相关连接数据
String url = strongTextEncryptor.encrypt(baseApplication.getDataSourceUrl());
String name = strongTextEncryptor.encrypt(baseApplication.getDataSourceUserName());
String password = strongTextEncryptor.encrypt(baseApplication.getDataSourcePassword());
String senderAddr = strongTextEncryptor.encrypt(baseApplication.getMailSenderAddr());
log.info("-------strong--------");
log.info("---url---");
log.info(url);
log.info("---name---");
log.info(name);
log.info("---password---");
log.info(password);
}
}
每次运行得到的加密字符串是不一样的
;
在这里我们采用 强加密 的方式作为示例说明;
我们把生成后的加密内容拷贝到配置文件进行替换;
src/main/resources/application.yml
server:
port: 9002
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: ENC(fwJbjvpLdv6BtS5GpAuhtPXtq4zpZEkl4oY1Zwy6NjvWkmMXEaV4nwDJlU3PuMLgrlMDBm13TDNZVFN+UH5YJmP62Ichojq9oWfZQBxfIMBDB4O13VbJ5L5VqwXiyH474YPBRzK9wKU=)
username: ENC(1H1Bd2ZhgDLDgcuaIcn/Cw==)
password: ENC(WyhyDX7I+Nm2jwsVKC13Wyj5y6pjH51y)
#jasypt加密的密匙
jasypt:
encryptor:
# 加密所需的salt(盐)
# 加密方式和算法一定要对应一致
# BasicTextEncryptor 对应加密方式:PBEWithMD5AndDES,StrongTextEncryptor 对应加密方式: PBEWithMD5AndTripleDES
# 部署时配置salt(盐)值 java -jar -Djasypt.encryptor.password=1qaz2wsx3edc -Djasypt.encryptor.algorithm=PBEWithMD5AndDES xxx.jar
# 或者在服务器的环境变量里配置,进一步提高安全性
# 打开/etc/profile文件 vim /etc/profile
# 文件末尾插入 export JASYPT_PASSWORD = SALT
# 文件末尾插入 export JASYPT_ALGORITHM = ALGORITHM
# 编译 source /etc/profile
# 运行 java -jar -Djasypt.encryptor.password=${JASYPT_PASSWORD} -Djasypt.encryptor.algorithm=${JASYPT_ALGORITHM} xxx.jar
password: 1qaz2wsx3edc
# 默认加密方式PBEWithMD5AndDES,可以更改为PBEWithMD5AndTripleDES
algorithm: PBEWithMD5AndTripleDES
ENC 是固定内部方法,一定要记得加上
;
此时重启项目,连接数据库成功;
如果说明文不加密是裸奔,把加密配置写在文件里,也相当于是皇帝的新衣,依然没有什么安全性可言,所以一定要把秘钥和算法加密方式,从配置文件中移除;
此时配置文件应该是:
server:
port: 9002
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: ENC(fwJbjvpLdv6BtS5GpAuhtPXtq4zpZEkl4oY1Zwy6NjvWkmMXEaV4nwDJlU3PuMLgrlMDBm13TDNZVFN+UH5YJmP62Ichojq9oWfZQBxfIMBDB4O13VbJ5L5VqwXiyH474YPBRzK9wKU=)
username: ENC(1H1Bd2ZhgDLDgcuaIcn/Cw==)
password: ENC(WyhyDX7I+Nm2jwsVKC13Wyj5y6pjH51y)
那么移除秘钥后,我们如何正常运行项目呢?
在环境变量中添加:
-Djasypt.encryptor.password=1qaz2wsx3edc -Djasypt.encryptor.algorithm=PBEWithMD5AndTripleDES
如图:
有两种方式:
第一种
java -jar -Djasypt.encryptor.password=1qaz2wsx3edc -Djasypt.encryptor.algorithm=PBEWithMD5AndDES xxx.jar
第二种:安全性高点
# 或者在服务器的环境变量里配置,进一步提高安全性
# 打开/etc/profile文件 vim /etc/profile
# 文件末尾插入 export JASYPT_PASSWORD = SALT
# 文件末尾插入 export JASYPT_ALGORITHM = ALGORITHM
# 编译 source /etc/profile
# 运行 java -jar -Djasypt.encryptor.password=${JASYPT_PASSWORD} -Djasypt.encryptor.algorithm=${JASYPT_ALGORITHM} xxx.jar
以上就是加密的方法,第二种比较安全;
加密不仅仅可以加密数据库连接信息,也可以加密你认为比较隐私的数据;
2.1.0
版本,打包后,在Window和Mac,运行很正常,但是到我的服务器Centos6, 一直报错,Failed to bind properties under 'spring.datasource.password' to java.lang.String
官方ISSUE:https://github.com/ulisesbocchio/jasypt-spring-boot/issues/154/
应该是版本问题,所以我尝试使用了3.0.3版本
<dependency>
<groupId>com.github.ulisesbocchiogroupId>
<artifactId>jasypt-spring-boot-starterartifactId>
<version>3.0.3version>
dependency>
工具类方法
package com.scaffold.test.utils;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
/**
* Jasypt 3.0.3 加密
* @author alex
*/
public class JasyptUtil {
/**
* 配置项
* @param password 加密使用的盐值
* @return config
*/
public static SimpleStringPBEConfig cryptor(String password){
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(password);
config.setAlgorithm("PBEWithMD5AndDES");
config.setKeyObtentionIterations("1000");
config.setPoolSize("1");
config.setProviderName("SunJCE");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
config.setStringOutputType("base64");
return config;
}
/**
* 加密
* @param salt 加密使用的盐值
* @param value 被加密的值
* @return string
*/
public static String encypt(String salt, String value){
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
encryptor.setConfig(cryptor(salt));
return encryptor.encrypt(value);
}
/**
* 解密
* @param salt 加密使用的盐值
* @param value 加密后的密文
* @return string
*/
public static String decypt(String salt, String value){
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
encryptor.setConfig(cryptor(salt));
return encryptor.decrypt(value);
}
public static void main(String[] args) {
String encryptPwd = encypt("salt", "1qaz2345");
System.out.println(encryptPwd);
String decryptPwd = decypt("salt", encryptPwd);
System.out.println(decryptPwd);
}
}
本地DEV配置也之前有所不同
#jasypt加密的密匙
jasypt:
encryptor:
# 3.0.0 之前版本
# # 加密所需的salt(盐)
# # 加密方式和算法一定要对应一致
# # BasicTextEncryptor 对应加密方式:PBEWithMD5AndDES,StrongTextEncryptor 对应加密方式: PBEWithMD5AndTripleDES
# # 部署时配置salt(盐)值 java -jar -Djasypt.encryptor.password=1qaz2wsx3edc -Djasypt.encryptor.algorithm=PBEWithMD5AndDES xxx.jar
# # 或者在服务器的环境变量里配置,进一步提高安全性
# # 打开/etc/profile文件 vim /etc/profile
# # 文件末尾插入 export JASYPT_PASSWORD = SALT
# # 文件末尾插入 export JASYPT_ALGORITHM = ALGORITHM
# # 编译 source /etc/profile
# # 运行 java -jar -Djasypt.encryptor.password=${JASYPT_PASSWORD} -Djasypt.encryptor.algorithm=${JASYPT_ALGORITHM} xxx.jar
# password: salt
# # 默认加密方式PBEWithMD5AndDES,可以更改为PBEWithMD5AndTripleDES
# algorithm: PBEWithMD5AndTripleDES
# 3.0.0 以后
password: salt
# 加密算法设置
algorithm: PBEWithMD5AndDES
iv-generator-classname: org.jasypt.iv.NoIvGenerator
生产环境部署,同之前 3.2 服务器部署,不过要多一个iv-generator-classname
#jasypt加密的密匙
jasypt:
encryptor:
iv-generator-classname: org.jasypt.iv.NoIvGenerator
CentOs6 服务器部署后,完美解决问题,看来还是版本问题;
本章完结;