0。问题背景使用过SpringBoot框架的应该都知道,SpringBoot有一个主应用配置文件,里面涉及敏感的配置信息,比如各种中间件的连接用户名和密码信息,以及各种第三方KEY、秘钥等.这种敏感信息如果直接放在配置文件中肯定是不安全的,甚至在很多行业和领域(比如:支付领域)也是不合规的,所以需要对敏感的配置信息进行保护在春季启动。那么,你还在让你的SpringBoot系统裸奔吗?如果是,不妨看看本文栈长分享的4个方法,让你的系统不再裸奔!1、配置中心(支持自动解密)我觉得要看你的架构。如果使用外部第三方配置中心(支持自动解密的),则可以将所有配置信息存储在配置中心。例如SpringCloud生态中的配置中心可以使用自己的加解密机制来保护敏感信息:spring:datasource:username:'{cipher}t1s293294187a31f35dea15e8bafaf7774532xxcc20d6d6dd0dfa5ae753d6836'需要加密的内容以{cipher}开头,并且注意使用单引号包裹,具体可以参考文章《Spring Cloud 配置中心内容加密》。SpringBoot配置文件只存储了一些无关紧要的配置。你用的是哪个配置中心?支付配置是否加解密?欢迎分享!如果没有使用配置中心怎么办?比如在传统的SpringBootMVC项目中,所有的代码和配置几乎都在同一个项目中。SpringBoot中的核心配置文件是application.yml(.properties)文件。如何保护敏感的配置信息?继续阅读!2、数据库机制可以将所有配置信息存储在数据库中,系统启动时加载到内存中。存储时,敏感信息采用对称加密算法加密存储,加载时自动解密到内存。这是最传统的配置管理方式。其实你也可以把它理解成一个原始简单的配置中心,只是功能没有那么强大,因为现在很多配置中心都是将配置存储在数据库中,然后提供一系列的配置管理能力。这里的数据库可以是关系型数据库(MySQL、Oracle)、内存数据库(Redis、Zookeeper)等,都是常用的中间件技术。3、自定义加解密机制也看此时的使用程度。如果只是简单的数据库连接池信息,那么可以考虑使用现有系统中的对称加密算法,结合连接池数据源类实现自定义加解密机制,比如我们可以模仿SpringCloud加密机制:先用系统已有的对称加密算法加密数据库连接信息:spring:datasource:username:'{cipher}t1s293294187a31f35dea15e8bafaf7774532xxcc20d6d6dd0dfa5ae753d6836'排除SpringBoot系统自带的数据源自动配置,然后组装自己的数据源SpringBean。判断获取到的配置值是否以标识符{cipher}开头,如果是则使用系统约定的对称加密算法解密,然后设置数据源,例如://示例代码@BeanpublicDataSourcedataSource(){数据源dataSource=newDruidDataSource();//解密字符串username=this.getUsername();if(username.startWith('{cipher}')){username=Encrypt.decrypt(username,this.getKey()))}dataSource.setUsername(username);...returndataSource;}SpringBoot的基础就不介绍了。我推荐这个实用教程。教程和示例源码都已上传:https://github.com/javastacks...这个简单易用,没有引入任何额外的第三方包。如果您也在使用自定义数据源,或者这种手动加解密机制可以满足保护其他敏感配置的需求,那么此方案供您参考。上面介绍的自定义加解密机制可以满足一般需求。如果是SpringBoot自动配置场景,比如数据源自动配置,Redis自动配置等,系统启动时默认会自动配置这个。我们不能干涉手动解密。这种情况下,我们需要考虑在框架层进行介入,在SpringBoot框架读取配置时进行拦截解密,或者使用第三方框架,比较常用的是:JasyptSpringBoot。4.JasyptSpringBootJasyptSpringBoot是一个为SpringBoot项目中的属性提供加密支持的框架。支持的版本为SpringBoot1.x~2.x。stackleader写文章的时候,现在已经有1.8K+的Star数了,人气还是很高的。开源地址:https://github.com/ulisesbocc...本开源项目更新也很及时。最新更新支持SpringBoot2.5.4!在此,栈长免费分享给大家一份SpringBoot学习笔记。理论和实践非常完备,助你快速上手SpringBoot。4.1JasyptSpringBoot实战JasyptSpringBoot有三种集成方式:1、如果开启了SpringBoot的自动配置(使用@SpringBootApplication或@EnableAutoConfiguration注解):只需要添加jasypt-spring-boot-starter依赖即可,其中2.添加jasypt-spring-boot依赖,在Spring主配置类中添加@EnableEncryptableProperties注解,将在整个Spring环境中启用可加密属性;3、增加jasypt-spring-boot依赖使用@EncrytablePropertySource注解声明各个可加密参数,仅适用于独立配置参数的加解密;一般SpringBoot都会开启自动配置,然后排除个别的自动配置,所以很少会出现自动配置完全关闭的情况,否则使用SpringBoot意义不大。这里我们使用第一种集成方式进行演示。4.1.1引入依赖核心依赖:com.github.ulisesbocchiojasypt-spring-boot-starter3.0.4Maven插件(可选)com.github.ulisesbocchiojasypt-maven-plugin${jasypt-spring-boot.version}4.1.2添加keyjasypt:encryptor:password:G9w0BAQEFAASCBKYwggSiAgEAAoIBAQCproperty:prefix:"ENC@["suffix:"]"这个jasypt.encryptor的.password参数是必需的,相当于Salt(盐),保证密码安全。prefix和prefix是用户定义的密码字符串标识符。如果未配置,则默认为:ENC(...)。4.1.3敏感信息加密/***来源微信公众号:Java技术栈*作者:栈长*/@Slf4j@RunWith(SpringRunner.class)@SpringBootTestpublicclassJasyptTest{@AutowiredprivateStringEncryptorstringEncryptor;/***来源微信公众号:Java技术栈*作者:StackManager*/@Testpublicvoidencrypt(){StringusernameEnc=stringEncryptor.encrypt("javastack");StringpasswordEnc=stringEncryptor.encrypt("javastack.cn");log.info("测试用户名加密为{}",usernameEnc);log.info("测试密码加密为{}",passwordEnc);log.info("测试用户名是{}",stringEncryptor.decrypt(usernameEnc));log.info("测试密码为{}",stringEncryptor.decrypt(passwordEnc));}}这里我注入了一个StringEncryptor,它的类结构图如下:如果没有自定义StringEncryptor,JasyptSpringBoot的自动配置会默认创建一个StringEncryptor实例,直接使用即可。其构造函数的默认值如下:KeyRequiredDefaultValuejasypt.encryptor.passwordTrue-jasypt.encryptor.algorithmFalsePBEWITHHMACSHA512ANDAES_256jasypt.encryptor.key-obtention-iterationsFalse1000jasypt.encryptor.pool-sizeFalse1jasypt.encryptor.provider-nameFalseSunJCEjasypt.encryptor.provider-class-nameFalsenulljasypt.encryptor.salt-generator-classnameFalseorg.jasyptomgenerator.AndencryptorgeneratorSaltiv.Range加密器.provider-class-nameFalsenulljasypt.encryptor.classnameFalseorg.jasypt.iv.RandomIvGeneratorjasypt.encryptor.string-output-typeFalsebase64jasypt.encryptor.proxy-property-sourcesFalsefalsejasypt.encryptor.skip-property-sourcesFalseemptylist然后运行测试用例,看到测试结果:加解密成功!!另外通过DEBUG调试可以看到是一个DefaultLazyEncryptor实例:当然也支持自定义Encryptor,需要的话可以自定义如果不想使用这种方式生成密文,也可以使用Maven插件,这就是为什么需要添加Maven插件(可选),使用方法如下:mvnjasypt:encrypt-value-Djasypt.encryptor.password="G9w0BAQEFAASCBKYwggSiAgEAAoIBAQC"-Djasypt.plugin.value="javastack"4.1.4敏感信息解密将上??一步生成的密文填入应用配置文件:javastack:username:ENC@[K4DsOasic/5Cvu2Y6Ca5dyaw2+eejgqRfhDWB0itMWRONrIN+wLy3xkGword:@[UeZWoPt3ZhSs2wPUAKTF21dgnhzimB+FNNiQjpJoPEhwYzI5WH3IWboZ5Wn+5Rgf]注意ENC@[]占位符就是上面的自定义配置。然后写个程序试试打印出来:/***来源微信公众号:Java技术栈*作者:栈长*/@Slf4j@SpringBootApplicationpublicclassApplication{@Value("${javastack.username}")私有字符串用户名;@Value("${javastack.password}")私有字符串密码;/***来源微信公众号:Java技术栈*作者:栈管理员*/publicstaticvoidmain(String[]args){SpringApplication.run(Application.class);}/***来源微信公众号:Java技术栈*作者:栈长*/@BeanpublicCommandLineRunnercommandLineRunner(){return(args)->{log.info("javastack.username={}",username);log.info("javastack.password={}",密码);};}}栈长写了一个CommandLineRunner,在系统启动后打印出密文原文。如果需要做任何处理,直接注入打印看看是不是纯文本就可以了。系统启动后:结果正常,自动解密成功。本教程所有实战源码已上传到本仓库:https://github.com/javastacks...可以点击Star持续更新~4.2KeySecurity我们将Jasyptkey(密码)保存在应用中configuration文件中,这样的敏感信息还在项目代码中,不太安全。建议传入命令行参数,比如在IDEA中设置:如果是生产环境,可以传入命令:java-Djasypt.encryptor.password=password-jarxx.jar甚至可以配置在服务器环境变量,因为StringEncryptor可以通过系统参数、配置文件、命令行参数、环境变量等来构造。这样一来,SpringBoot中的配置信息就完全安全了!JasyptSpringBoot的功能远不止于此,实际功能更强大。这里stackmanager只介绍简单的应用。更多的定制化需求,可以参考官方文档,里面有更详细的教程。4.3JasyptSpringBoot原理JasyptSpringBoot注册了一个Spring后处理器,它修改SpringEnvironment中包含的所有PropertySource对象,并根据Jasypt的配置约定对属性进行加密和解密。来一波源码:源码有点复杂。一路找到了解密器DefaultPropertyResolver,然后它也注入了StringEncryptor实例。当获取配置时,它会对其进行解密,然后返回。另外这个Resolver还支持自定义,有兴趣的可以深入研究一下。综上所述,今天栈长介绍了4种SpringBoot保护敏感配置信息的方法。总结一下:配置中心(支持自动加解密)自定义加解密机制数据库机制JasyptSpringBoot(第三方加解密方案)总之就是敏感不要把信息放在SpringBoot的配置文件里。如果一定要放,就必须加密。这四种解决方案各有各的应用场景,需要结合公司现有的架构和系统规模进行取舍。另外,之前写的这篇文章,也供大家参考。本节教程所有实战源码已上传至本仓库:https://github.com/javastacks...欢迎Star关注学习,SpringBoot实战教程会持续更新将来。好了,今天的分享就到这里。稍后栈长会分享更多有趣的Java技术和最新的技术资料。关注公众号Java技术栈第一时间推送。我也会分享主流的Java面试题和参考答案。全部搞定后在公众号后台回复关键字“面试”刷题。版权声明:本文为公众号《Java技术栈》原创。转载、引用本文内容请注明出处。抄袭、洗稿均属侵权投诉,后果自负,并保留追究法律责任的权利。近期热点文章推荐:1.1000+Java面试题及答案(2022最新版)2.厉害了!Java协程来了。..3.SpringBoot2.x教程,太全面了!4.不要用爆破爆满画面,试试装饰者模式,这才是优雅的方式!!5.《Java开发手册(嵩山版)》最新发布,赶快下载吧!感觉不错,别忘了点赞+转发!