SpringBoot-配置文件中敏感信息的加密保姆级教程
前言
公司安全部门检查,要求系统配置文件中的敏感信息如数据库密码等,进行加密处理,否则将受到公司的安全处罚,无奈只要按照公司要求,对springboot
项目配置文件的敏感信息进行加密和解密处理。详细教程如下。
快速上手
第一步:在pom.xml添加第三方依赖
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
第二步:添加加密配置
方式一:通过配置问年间 application.yml中增加jasypt配置
jasypt:
encryptor:
# 盐值
password: 123
# 指定加密方式
algorithm: PBEWithMD5AndDES
iv-generator-classname: org.jasypt.iv.NoIvGenerator
property:
# 标识为加密属性的前缀
prefix: ENC(
# 标识为加密属性的后缀
suffix: )
- 这样还是会把加密信息暴漏,推荐使用配置类更加安全
方式二:通过配置类添加加密配置
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class EncryptConfig {
/**
* 自定义 StringEncryptor,覆盖默认的 StringEncryptor
* bean 名称是必需的,从 1.5 版开始按名称检测自定义字符串加密程序,默认 bean 名称为:jasyptStringEncryptor
*
*/
@Bean("jasyptStringEncryptor")
public StringEncryptor jasyptStringEncryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword("tarzan");
config.setPoolSize("1");
config.setAlgorithm("PBEWithMD5AndDES");
config.setKeyObtentionIterations("1000");
config.setProviderName("SunJCE");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
config.setStringOutputType("base64");
encryptor.setConfig(config);
return encryptor;
}
}
第三步:在配置文件application.yml中密文替代明文。
spring:
redis:
##redis 单机环境配置
host: ${REDIS_HOST:127.0.0.1}
port: 6379
password: ${REDIS_PASSWORD:ENC(YiSSNr7KKHbglJ0Er+YSOCr22X1Xwgi+NX6eqPARS48=)}
database: 5
ssl: false
data:
mongodb:
database: ${MONGO_DATABASE:work_face_tmzk5}
host: ${MONGO_HOST:127.0.0.1}
username: ${MONGO_USERNAME:tarzan-mongo}
password: ${MONGO_PASSWORD:ENC(XYZ6QH/B1YnSQhTgqtq9tqn/6NIxotNmBDF8ve57Vh0=)}
datasource:
url: jdbc:postgresql://${POSTGRES_HOST:127.0.0.1}:${POSTGRES_PORT:5432}/${POSTGRES_DATABASE:coalface_safety}
username: ${POSTGRES_USERNAME:postgres}
password: ${POSTGRES_PASSWORD:ENC(YiSSNr7KKHbglJ0Er+YSOCr22X1Xwgi+NX6eqPARS48=)}
driver-class-name: org.postgresql.Driver
-
ENC(YiSSNr7KKHbglJ0Er+YSOCr22X1Xwgi+NX6eqPARS48=) 只能单独使用,不能和其他文本拼接,下面是个
错误例子
:spring: data: mongodb: database: ${MONGO_DATABASE:work_face_szls} uri: mongodb://glqxzh:ENC(YiSSNr7KKHbglJ0Er+YSOCr22X1Xwgi+NX6eqPARS48=):27017
第四步::启动类加入开启加密注解
@EnableEncryptableProperties
@SpringBootApplication(scanBasePackages = AppConstant.BASE_PACKAGES,exclude = {TenantDataSourceConfiguration.class})
public class CoalfaceSafetyApplication {
public static void main (String[] args) {
ApplicationContext context =BladeApplication.run("coalface-safety", CoalfaceSafetyApplication.class, args);
}
- 完成以上四步即可,启动后,会自动解密配置信息。
加密工具类
在第三步使用的加密信息,需要工具类生成,代码如下:
package org.springblade.coalface.utils;
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.PBEConfig;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
public class JasyptUtils {
/**
* {@link StringEncryptor} 加解密。
* 同一个密钥(secretKey)对同一个内容执行加密,生成的密文都是不一样的,但是根据根据这些密文解密成明文都是可以.
* 1、Jasypt 默认使用 {@link StringEncryptor} 来解密全局配置文件中的属性,所以提供密文时,也需要提供 {@link StringEncryptor} 加密的密文
* 2、{@link StringEncryptor} 接口有很多的实现类,比如常用的 {@link PooledPBEStringEncryptor}
* 3、setConfig(final PBEConfig config):为对象设置 {@link PBEConfig} 配置对象
* 4、encrypt(final String message):加密内容
* 5、decrypt(final String encryptedMessage):解密内容
*
* @param secretKey :密钥。加/解密必须使用同一个密钥
* @param message :加/解密的内容
* @param isEncrypt :true 表示加密、false 表示解密
* @return
*/
public static String stringEncryptor(String secretKey, String message, boolean isEncrypt) {
PooledPBEStringEncryptor pooledPBEStringEncryptor = new PooledPBEStringEncryptor();
pooledPBEStringEncryptor.setConfig(getSimpleStringPBEConfig(secretKey));
String result = isEncrypt ? pooledPBEStringEncryptor.encrypt(message) : pooledPBEStringEncryptor.decrypt(message);
return result;
}
/**
* 设置 {@link PBEConfig} 配置对象,SimpleStringPBEConfig 是它的实现类
* 1、所有的配置项建议与全局配置文件中的配置项保持一致,特别是 password、algorithm 等等选项,如果不一致,则应用启动时解密失败而报错.
* 2、setPassword(final String password):设置加密密钥,必须与全局配置文件中配置的保存一致,否则应用启动时会解密失败而报错.
* 3、setPoolSize(final String poolSize):设置要创建的加密程序池的大小.
* 4、setAlgorithm(final String algorithm): 设置加密算法的值, 此算法必须由 JCE 提供程序支持
* 5、setKeyObtentionIterations: 设置应用于获取加密密钥的哈希迭代次数。
* 6、setProviderName(final String providerName):设置要请求加密算法的安全提供程序的名称
* 7、setSaltGeneratorClassName:设置 Sal 发生器
* 8、setIvGeneratorClassName:设置 IV 发生器
* 9、setStringOutputType:设置字符串输出的编码形式。可用的编码类型有 base64、hexadecimal
*
* @param secretKey
* @return
*/
private static SimpleStringPBEConfig getSimpleStringPBEConfig(String secretKey) {
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(secretKey);
config.setPoolSize("1");
config.setAlgorithm("PBEWithMD5AndDES");
config.setKeyObtentionIterations("1000");
config.setProviderName("SunJCE");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
config.setStringOutputType("base64");
return config;
}
public static void main(String[] args) throws Exception {
String message = "@5Rd!TC2CBA";
String password = "tarzan";
//一个同样的密码和秘钥,每次执行加密,密文都是不一样的。但是解密是没问题的。
String jasyptEncrypt = stringEncryptor(password, message, true);
System.out.println(jasyptEncrypt);
String jasyptEncrypt1 = stringEncryptor(password, jasyptEncrypt, false);
System.out.println(jasyptEncrypt1);
}
}
- 修改主方法中的
message
和password
即可。message
为需要加密的文本,password
是加密盐值。
当然你也可以讲加密方法封装成接口调用,示例代码如下:
@Resource
private StringEncryptor stringEncryptor;
/**
* http://localhost:8080/jasypt/encryptor?message=12日下午17点执行任务&isEncrypt=true
* http://localhost:8080/jasypt/encryptor?message=702EAA3755766C567F62E83273681A90DC684B6AFADD5CD84691778DAF4A1466E13CE0720E8BABC06081A5D6DBD90EA1&isEncrypt=false
* 在线使用 {@link StringEncryptor} 加解密消息。
*
* @param message 加/解密的内容
* @param isEncrypt true 表示加密、false 表示解密
* @return
*/
@GetMapping("jasypt/encryptor")
public ObjectNode encrypt(@RequestParam String message, @RequestParam boolean isEncrypt) {
JsonNodeFactory nodeFactory = JsonNodeFactory.instance;
String encrypt = isEncrypt ? stringEncryptor.encrypt(message) : stringEncryptor.decrypt(message);
ObjectNode objectNode = nodeFactory.objectNode();
objectNode.put("code", 200);
objectNode.put("data", encrypt);
return objectNode;
}