SpringBoot配置文件内容加密,实现敏感信息保护 - 第431篇
历史文章(累计400+篇文章)
SpringBoot使用thymeleaf实现布局方案二,方案在手说走就走 - 第425篇
SpringBoot/Spring扩展点系列之初出茅庐ApplicationContextInitializer - 第426篇
SpringBoot/Spring扩展点BeanDefinitionRegistryPostProcessor - 第427篇
SpringBoot/Spring扩展点系列之叱咤风云BeanFactoryPostProcessor - 第428篇
SpringBoot扩展点系列之InstantiationAwareBeanPostProcessor模拟AOP - 第429篇一款利用人工智能生成模型来合成代码的工具Copilot - 第430篇
悟纤:师傅,师傅,你在哪里?
师傅:为师睡午觉刚醒呐。
悟纤:师傅,你说你在那里享福呢,徒儿都要愁死了。
师傅:徒儿,这是怎么了,闹得哪出呢?
悟纤:师傅,我觉得配置文件的重要配置,明文显示不是很安全呐,有没有办法,加密显示呐。
师傅:那是肯定的有的。今天咱们就一起来瞅一瞅这配置加密,以此来实现敏感信息的保护。
悟纤:那师傅,赶紧的呗~ 我已经迫不及待了。
导读
我们的配置文件中,其实包含着大量与安全相关的敏感信息,比如:数据库的账号密码、一些服务的密钥等。这些信息一旦泄露,对于企业的重要数据资产,那是相当危险的。所以,对于这些配置文件中存在的敏感信息进行加密,是每个成熟开发团队都一定会去的事。
一、配置信息加密方案
在前面的章节中,我们有学习过Spring的扩展点,如果把扩展点搞明白的话,就可以来实现一套加密解密的方案了;另外既然我们能想到要对配置文件的重要信息加密,那么这个技术方案一定是就存在了,所以可以找找成熟的方案直接使用,总结一下:
(1)方案一:借助Spring的扩展点自我进行实现加密解密。
(2)方案二:使用第三方框架来实现加密解密(实际上第三方框架底层的实现,也是借助了Spring的扩展点)。
二、jasypt
这一节,我们就先来看看第三方框架jasypt如何来进行加密解密。
2.1 jasypt是什么?
Jasypt的github地址:
https://github.com/jasypt/jasypt
看官网的介绍:Jasypt (Java Simplified Encryption) 是一个 java 库,它允许开发人员以最小的努力将基本的加密功能添加到他/她的项目中,而无需深入了解密码学的工作原理。
2.2 Jasypt要怎么用?
核心步骤,就两个:
(1)添加jasypt依赖
(2)配置文件添加配置
2.3 Jasypt实战
2.3.1 构建SpringBoot项目
构建一个SpringBoot项目,取名为:spring-boot-jasypt-example。
项目名,取啥不重要,你高兴就行。
2.3.2 添加依赖包
在pom.xml文件,添加jasypt的starter:
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.4</version>
</dependency>
还有一个就是插件:
<plugin>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-maven-plugin</artifactId>
<version>3.0.4</version>
</plugin>
插件是非必须的,本节讲解需要用到,所以先引入。
总的pom.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.kfit</groupId>
<artifactId>spring-boot-jasypt-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-jasypt-example</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-maven-plugin</artifactId>
<version>3.0.4</version>
</plugin>
</plugins>
</build>
</project>
2.3.3 添加配置信息
在application.properties添加配置:
# 配置加密时使用的密码/加密的盐
jasypt.encryptor.password=wuqian
# 例子用的密码
datasource.password = 123456
redis.password = 123456
jasypt.encryptor.password这个配置很重要,可以理解是加密的密码/加密的盐。
实际中,这个直接配置在配置文件,是否合理?大家可以思考一下,我们想接着往下讲解。
2.3.4 配置加密
可以发现,现在配置文件的密码还是明文呢?那么我们如何实现加密呢?
(1)方案1:命令行方式,使用java命令运行jar
找到jasypt-x.x..jar运行如下命令:
java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input="123456" password=wuqian algorithm=PBEWithMD5AndDES
input :明文密码
password:要加的盐(可自己设置)
algorithm:加密算法,这里使用 PBEWithMD5AndDES
结果如下,OUTPUT就是加密之后的密文(密码)
将加密的密文,替换掉配置文件的内容即可。
(2)方案2:代码方式
package com.kfit;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
/**
*
*
* @author 悟纤「公众号SpringBoot」
* @date 2022-06-20
* @slogan 大道至简 悟在天成
*/
@RestController
public class DemoController {
@Value("${datasource.password}")
private String dataSourcePwd;
@Value("${redis.password}")
private String redisPwd;
@PostConstruct
public void init(){
System.out.println("dataSourcePwd:"+dataSourcePwd+",redisPwd:"+redisPwd);
}
}
(3)方案3:插件的插件
如果使用插件的方式,就需要添加插件jasypt-maven-plugin(已经在前面配置的时候,一起添加了);如果不是使用这种方式的话,这个插件就可以不用添加。
首先,修改要加密的内容,用DEC()将待加密内容包裹起来,比如:
datasource.password = DEC(123456)
这个的作用,就是jasypt插件,才能知道要加密那些配置文件的内容。
紧接着使用使用jasypt-maven-plugin插件来给DEC()包裹的内容实现批量加密。
在终端中执行下面的命令:
mvn jasypt:encrypt -Djasypt.encryptor.password=wuqian
注意:这里-Djasypt.encryptor.password参数必须与配置文件中的一致,不然后面会解密失败。
执行之后,重新查看配置文件,可以看到,自动变成了:
其中,ENC()跟DEC()一样都是jasypt提供的标识,分别用来标识括号内的是加密后的内容和待加密的内容。
如果当前配置文件已经都是ENC()内容了,那么我们可以通过下面的命令来解密配置文件,查看原始信息:
特别说明:该操作不会修改配置文件,只会在控制台输出解密结果。
2.3.5 测试类
写个测试类,看看在代码中,是否可以获取到原文?
package com.kfit;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
/**
*
*
* @author 悟纤「公众号SpringBoot」
* @date 2022-06-20
* @slogan 大道至简 悟在天成
*/
@RestController
public class DemoController {
@Value("${datasource.password}")
private String dataSourcePwd;
@Value("${redis.password}")
private String redisPwd;
@PostConstruct
public void init(){
System.out.println("dataSourcePwd:"+dataSourcePwd+",redisPwd:"+redisPwd);
}
}
执行测试,查看下结果:
三、加密盐安全问题
之前是把盐值存储在配置文件实际上是否加密都成了问题了,那么这个怎么办呢?
很简单盐值应该放在系统属性、命令行或是环境变量来使用。
(1)自定义加密前后缀,让加密更安全。
默认是ENC,jasypt.encryptor.property.prefix配置来重新定义。
(2)使用自定义加密器。
使用的是默认的加密规则,这一点会让当自定义加密密钥泄漏时可能变得不安全。为此我们可以自定义加密规则。
(3)加密密钥不要写在配置文件中
方式一:直接作为程序启动时的命令行参数来带入
java -jar xxx.jar --jasypt.encryptor.password=wuqian
方式二:直接作为程序启动时的应用环境变量来带入
java -Djasypt.encryptor.password=wuqian -jar xxx.jar
方式三:甚至可以作为系统环境变量的方式来带入
比方说,我们提前设置好系统环境变量JASYPT_ENCRYPTOR_PASSWORD = wuqian,则直接在Spring Boot的项目配置文件中做如下配置即可:
jasypt.encryptor.password=${JASYPT_ENCRYPTOR_PASSWORD:}
总结
(1)jasypt的基本使用,添加依赖,写配置信息。
(2)jasypt的3种加密方式:命令行、代码、插件。
(3)加密盐不放在配置文件的3中方式:命令行参数、应用环境变量、系统环境变量。
我就是我,是颜色不一样的烟火。
我就是我,是与众不同的小苹果。
à悟空学院:https://t.cn/Rg3fKJD
学院中有Spring Boot相关的课程!点击「阅读原文」进行查看!
SpringBoot视频:http://t.cn/A6ZagYTi
SpringBoot交流平台:https://t.cn/R3QDhU0
SpringSecurity5.0视频:http://t.cn/A6ZadMBe
ShardingJDBC分库分表:http://t.cn/A6ZarrqS
分布式事务解决方案:http://t.cn/A6ZaBnIr
JVM内存模型调优实战:http://t.cn/A6wWMVqG
Spring入门到精通:https://t.cn/A6bFcDh4
大话设计模式之爱你:https://dwz.cn/wqO0MAy7