如何定义SpringBoot项目配置文件中密码的加密

前言项目中的配置文件会有密码的存在,例如数据库的密码、邮箱的密码、FTP的密码等 。
配置的密码以明文的方式暴露,并不是一种安全的方式,特别是大型项目的生产环境中,因为配置文件经手的(运维)人员可能很多,也可能是多方的(甲方、乙方甚至第三方) 。本文讲述基于 SpringBoot 项目对配置文件中的密码进行加密 。
本文实例中密码加密主要用到的是 Jasypt,一个JAVA的加解密库 。
加密步骤1、在项目中引入以下依赖 。
<dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot</artifactId><version>1.18</version></dependency><dependency><groupId>org.jasypt</groupId><artifactId>jasypt</artifactId><version>1.9.2</version></dependency>2、在Application.yml文件中添加以下配置信息 。
# 配置文件密码加密配置jasypt:encryptor:password: EbfYkitulv73I2p0mXI50JMXoaxZTKJ7 # 秘钥algorithm: PBEWithMD5AndDES # 加密算法iv-generator-classname: org.jasypt.iv.NoIvGenerator

(1)从3.0.0jasypt-spring-boot 版本开始,默认的加密/解密算法已更改为PBEWITHHmacSHA512ANDAES_256;3.0.0以下版本默认为 PBEWithMD5AndDES;
(2)上述algorithm 不配置的话,其默认的秘钥也是 PBEWithMD5AndDES;
(3)以上的 jasypt.encryptor.password 并不是很多人理解的 salt(盐),这是加密密钥 。代码中的salt是随机生成的,长度默认为8位,生成类默认是 org.jasypt.salt.RandomSaltGenerator,可以通过配置 jasypt.encryptor.salt-generator-classname来修改 。
3、通过命令获取密文 。
java -cp /Users/shiyanfei/zlb/repository/repository-zlb/org/jasypt/jasypt/1.9.2/jasypt-1.9.2.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input="MySQL@1234" password=idss@2021 algorithm=PBEWithMD5AndDES终端执行上述命令会生成密文,其中:
  • /Users/shiyanfei/zlb/repository/repository-zlb/org/jasypt/jasypt/1.9.2/ 是 jasypt-1.9.2.jar 的路径(linux环境中应该是在/lib包下面),根据需求修改;
  • input 是明文密码,每一个密码都需要执行一次;
  • password 是秘钥 。
4、修改原来的密码配置
原来的明文密码值,改为 ENC(xxx) ,其中xxx是密文 。
例如:
1)MySQL
spring:datasource:url: jdbc:mysql://127.0.0.1:3306/ueba?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&&useSSL=falsedriver-class-name: com.mysql.jdbc.Driverusername: rootpassword: ENC(2RP1Vdsa+2wdSOgu2biAJkTCU9fnkUGD) 2)redis
spring:redis:database: 0host: 10.20.24.48port: 6379password: ENC(JjPTg5GOsjV9ZBIQ2CaHr+96UgMKBgIT) 5、添加注解
启动类上添加@EnableEncryptableProperties 。
思考:以上的步骤中,根据 Jasypt 的用法,基本上完成了对配置文件中密码的加密 。但是,请思考一下,这样处理是否真的安全合理?
优化如果按照严格的要求来,这样处理并不是完善的 。因为秘钥和密文都暴露出来,依然是不安全的 。那么,要如何处理呢?以下是我其中的一个思路,并已在项目中实践 。
1、首先,秘钥通过另一个小工具生成,该小工具与项目无关;
小工具是一个独立的完整程序,有打包脚本和启停脚本 。篇幅所限,已将源码上传至 GitHub 。
2、其次,秘钥不暴露在配置文件中,而写入代码中(正常情况下,秘钥基本不会变动);
/************************ CHANGE REPORT HISTORY ****************************** ** Product VERSION,UPDATED BY,UPDATE DATE* *DESCRIPTION OF CHANGE: modify(M),add(+),del(-)* *-----------------------------------------------------------------------------* * V3.0.12,shiyanfei,2021-09-14 * create* *************************** END OF CHANGE REPORT HISTORY ********************/package com.idss.radar.common.ums.bean;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;/** * @author : shiyanfei * @description : <p>自动配置加密信息</p> * @see : com.idss.radar.common.ums.bean * @since : 2021-09-14 */@Configurationpublic class EncryptorConfig {@Bean("jasyptStringEncryptor")public StringEncryptor jasyptStringEncryptor() {PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();SimpleStringPBEConfig config = new SimpleStringPBEConfig();config.setPassword("EbfYkitulv73I2p0mXI50JMXoaxZTKJ7");// 注释部分为配置默认config.setAlgorithm("PBEWithMD5AndDES");//config.setKeyObtentionIterations("1000");config.setPoolSize("1");//config.setProviderName("SunJCE");//config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");//config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");//config.setStringOutputType("base64");encryptor.setConfig(config);return encryptor;}}


推荐阅读