Spring Boot 番外 (03) - 敏感信息加密 Encrypt
在所有的应用中,我们会需要一些配置信息,其中难免会有一些敏感信息。 如果明文将他们放到仓库里,这些信息就会泄露。而如果我们不放在仓库里,又会给我们的部署带来麻烦。 因此,加密敏感信息就成了必要的需求了。
基于Spring Boot的容器特性,我们其实很容易切入配置文件的加载,来处理加密信息。
自制简单的解密处理
我们想要的是,把编码后的数据放到配置中,而在容器里拿到的却是解码后的内容。
所以首先我们得有一条绝密的字符串Hello World
,然后我们用复杂的BASE64算法进行编码,得到了SGVsbG8gV29ybGQ=
。
把它放到application.yaml
里。为了区别于未加密的信息,我们以base64:
开头:
data: base64:SGVsbG8gV29ybGQ=
现在我们可以开始写我们的解密处理器了
@AutoSpringFactories(EnvironmentPostProcessor.class)
public class CustomEncryptProcessor implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
HashMap<String, Object> map = new HashMap<>(); // 准备一个Map存储解密后的数据
for (PropertySource<?> ps : environment.getPropertySources()) { // 遍历所有的PropertySource
if (ps instanceof EnumerablePropertySource) { // 对于每一个可以遍历的PropertySource
EnumerablePropertySource eps = (EnumerablePropertySource) ps;
for (String name : eps.getPropertyNames()) { // 遍历所有的属性
Object value = eps.getProperty(name);
if (value instanceof String) { // 对于值是字符串的属性
String str = (String) value;
if (str.startsWith("base64:")) { // 如果以 base64: 开头
String decode = new String(Base64.getDecoder().decode(str.substring(7)));
map.put(name, decode); // 解码并放入Map里
}
}
}
}
}
PropertySource newPs = new MapPropertySource("custom-encrypt", map);
environment.getPropertySources().addFirst(newPs); // 将解密的数据放入环境变量,并处于第一优先级上
}
}
现在我们容器中就获得了解密的数据了,让我们来试一试获取它
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Autowired
public void init(@Value("${data}") String data) {
System.out.println(data);
}
}
执行程序,你就能够看到Hello World
了!
至此,我们的简易解密处理就完成了。
当然,我们的功能很简陋,而且其实单单BASE64也根本没有加密的效果。
其实这种基础设施在社区中早就有成熟的开源项目了,我们不需要重复造轮子。
下面就介绍其中最流行的工具jasypt-spring-boot
开源工具 jasypt-spring-boot
*这里只简单介绍基本功能,更多高级用法请参看项目主页。
安装依赖项
添加如下依赖
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
加密功能将通过Auto Configuration机制自动开启。
加密信息
默认的加密算法为PBEWITHHMACSHA512ANDAES_256
,你可以使用任何工具生成加密信息。
Jasypt
提供了插件可以便捷地生成加密信息:
mvn com.github.ulisesbocchio:jasypt-maven-plugin:encrypt-value -Djasypt.encryptor.password="xdean" -Djasypt.plugin.value="Hello World"
其中jasypt.encryptor.password
是你的密钥,而jasypt.plugin.value
则是你要加密的信息明文。
运行之后你就会得到密文ENC(aL2TRHEJqVUACdAwL851lI/fTXHSYNgu4gJEyGjJdnEqRRFqbyOvMd6iE7Jv0R6B)
Jasypt
通过ENC(XXX)
来识别加密信息,如果你通过其他方式生成密文,不要忘了包裹上ENC()
测试
现在我们可以把加密信息放到application.yml
中,然后运行应用。
为了解密数据,我们唯一要做的是提供一个名为jasypt.encryptor.password
的环境变量,即我们的密钥。
在这里测试代码为了方便执行,直接修改args
模拟从命令行输入。
@SpringBootApplication
public class JasyptApplication {
public static void main(String[] args) {
args = new String[]{"--jasypt.encryptor.password=xdean"}; // Mock从命令行传入
SpringApplication.run(JasyptApplication.class, args);
}
@Autowired
public void init(@Value("${jasypt-data}") String data) {
System.out.println(data);
}
}
运行程序即可看到Hello World
!