写点什么

拒绝裸奔,SpringBoot 集成 Jasypt 加密敏感信息

作者:IT学习日记
  • 2022 年 8 月 29 日
    广东
  • 本文字数:5356 字

    阅读完需:约 18 分钟

拒绝裸奔,SpringBoot集成Jasypt加密敏感信息

前言

  在互联网遍布社会各个角落的时代,伴随着的是安全问题总是层出不穷。 19 年 4 月,根据深圳市人民检察院微信消息,深圳某知名无人机企业的工程师因为泄露公司源代码到开源社区 Github 上而造成了公司巨大的损失,最终被判处有期徒刑 6 个月,罚款 20 万元。


  一般公司的核心业务代码中,都会存在与数据库、第三方通信的 secret key 等敏感信息,如果以明文的方式存储,一旦泄露,那将会给公司带来巨大的损失。 然而,许多中小型公司开发者对这方面的管理不够规范,所以很多敏感信息都是直接以明文形式存放到代码中,这样的项目存在的安全风险非常大。


  本篇文章通过讲解:Springboot 集成 Jasypt 对项目敏感信息进行加密,提高系统的安全性。



哪些信息需要加密

  一个系统中,一般和数据库、第三方系统等交互的信息都会存在相应的配置文件中,在配置文件中,所有涉及到信息安全的配置项都不应该以明文的形式存储,否则,一旦配置文件泄露,则会引出巨大的安全问题,常见的需要加密的信息项如下:


  • 访问数据库、缓存等涉及到的账号密码

  • 与第三方系统交互的 access key、秘钥

  • 其他涉及第三方通信的信息



敏感信息加密的作用

  第一:是为了防止人为误操作将代码泄漏时,第三方能够简单获取到系统中的敏感信息,从而可能对系统、数据库等造成破坏。


  其次是一般系统上线都会有代码安全检测的流程,像账号、密码等敏感数据以明文形式存储,一般都是审核不通过的,因此需要进行加密处理。


  最后,作为一名开发者,应该对自我有更高的要求,在开发过程中应该要考虑到潜在的风险,提供相应的处理预案。

选择加密的组件

  开源社区强大之处在于:有需求就有人奉献。Jasypt(全称:Java Simplified Encryption),它是一个 Java 类库,支持开发者无需深入 了解密码学相关工作原理,花费最小的代码在项目中添加基本的加密功能。


  Jasypt 官方使用文档:http://www.jasypt.org/

项目集成 Jasypt 方式

  jasypt-spring-boot 组件则是 Jasypt 提供对 Springboot 项目集成的依赖,刚好符合我们的需求,它支持以下 3 种方式集成到项目中。

方式一

  在 Springboot 应用程序中,如果使用了 @SpringBootApplication or @EnableAutoConfiguration 注解,则可以直接在 pom 文件中添加 jasypt-spring-boot 依赖,然后就可以在整个 Spring 环境中使用 jasypt 对属性进行加解密操作(属性包括:系统属性、环境属性、命令行参数、properties、yml 以及任何其他属性源)。


<dependency>        <groupId>com.github.ulisesbocchio</groupId>        <artifactId>jasypt-spring-boot-starter</artifactId>        <version>3.0.4</version></dependency>
复制代码



方式二

  如果项目中没有使用到 @SpringBootApplication or @EnableAutoConfiguration 注解,则可以通过以下两个步骤完成对 Jasypt 的集成。


  步骤一:pom 文件引入 jasypt 依赖


<dependency>        <groupId>com.github.ulisesbocchio</groupId>        <artifactId>jasypt-spring-boot</artifactId>        <version>3.0.4</version></dependency>
复制代码


  步骤二:在配置类中,添加 @EnableEncryptableProperties 注解,示例如下:


@Configuration@EnableEncryptablePropertiespublic class MyApplication {    ...}
复制代码


  通过这种方式,你的项目一样可以集成 Jasypt,并且可加密属性也可以在整个 Spring 环境中启用(属性包括:系统属性、环境属性、命令行参数、properties、yml 以及任何其他属性源)。



方式三

  如果项目中没有使用到 @SpringBootApplication or @EnableAutoConfiguration 注解,又不想在整个 Spring 环境中启用加密的属性,则可以使用该种方式,具体步骤如下:


  步骤一:pom 文件引入 jasypt 依赖


<dependency>        <groupId>com.github.ulisesbocchio</groupId>        <artifactId>jasypt-spring-boot</artifactId>        <version>3.0.4</version></dependency>
复制代码


  步骤二、在配置类中,使用 @EncryptablePropertySource 注解添加任意数量想要生效加密属性的配置文件路径,与 Spring 中 @PropertySource 注解的使用类似,示例如下:


@Configuration@EncryptablePropertySource(name = "EncryptedProperties", value = "classpath:encrypted.properties")public class MyApplication {    ...}
复制代码


  同时,还可以使用 @EncryptablePropertySources 注解对 @EncryptablePropertySource 配置进行分组,示例如下:


@Configuration@EncryptablePropertySources({@EncryptablePropertySource("classpath:encrypted.properties"),                         @EncryptablePropertySource("classpath:encrypted2.properties")})    public class MyApplication {        ...    }
复制代码


  说明:从 Jasypt 1.8 版本开始,@EncryptablePropertySource 注解支持配置 YAML 文件



Springboot 整合 Jasypt 实战

一、引入依赖

  说明,本项目使用技术栈是 spring-boot+jasypt,故使用上面介绍的第一种方式来在项目中集成 Jasypt,文章中只截取部分核心代码,全部代码会开发到 Github 和 Gitee 上。


<dependency>    <groupId>com.github.ulisesbocchio</groupId>    <artifactId>jasypt-spring-boot-starter</artifactId>    <version>3.0.4</version></dependency>
复制代码



二、配置文件中添加 Jasypt 配置信息

  1、配置 jasypt 参数


jasypt:  encryptor:    # 配置加密算法    algorithm: PBEWithMD5AndDES    iv-generator-classname: org.jasypt.iv.NoIvGenerator    property:      # 算法识别前缀(当算法发现配置文件中的值以这前缀开始,后缀结尾时,会使用指定算法解密)      prefix: IT(      # 算法识别后缀      suffix: )
复制代码


  2、配置加密算法秘钥 (该秘钥不能直接放在配置文件中,下面会具体总结秘钥存放的方式,从而保证安全性)




三、使用 Jasypt 对数据库账号和密码加密,并替换明文。


  替换后的配置信息:


spring:  application:    name: Jasypt-Learning  datasource:    url: jdbc:mysql://localhost:3306/user2?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai    username: IT(MIJueAfnYWsKa2kiR8Qrrw==)    password: IT(qH9m5vjj8RYULOASKdhlOw==)server:  port: 9090# 配置jasypt相关信息jasypt:  encryptor:    # 配置加密算法    algorithm: PBEWithMD5AndDES    iv-generator-classname: org.jasypt.iv.NoIvGenerator    property:      # 算法识别前缀(当算法发现配置文件中的值以这前缀开始,后缀结尾时,会使用指定算法解密)      prefix: IT(      # 算法识别后缀      suffix: )

复制代码


  Jasypt 加密有 3 种方式,具体如下:


  方式 1、使用代码生成加密串,代码工具如下:


public static void main(String[] args) {        String username = encrypt("root");        String password = encrypt("123456");        System.out.println(username);        System.out.println(password);    }
/** * 加密 * @param plaintext 明文密码 * @return */ public static String encrypt(String plaintext) { //加密工具 StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); //加密配置 EnvironmentStringPBEConfig config = new EnvironmentStringPBEConfig(); // 算法类型 config.setAlgorithm("PBEWithMD5AndDES"); //生成秘钥的公钥 config.setPassword("PEB123@321BEP"); //应用配置 encryptor.setConfig(config); //加密 String ciphertext = encryptor.encrypt(plaintext); return ciphertext; }
/** * 解密 * * @param ciphertext 待解密秘钥 * @return */ public static String decrypt(String ciphertext) { //加密工具 StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); //加密配置 EnvironmentStringPBEConfig config = new EnvironmentStringPBEConfig(); config.setAlgorithm("PBEWithMD5AndDES"); //生成秘钥的公钥 config.setPassword("PEB123@321BEP"); //应用配置 encryptor.setConfig(config); //解密 String pText = encryptor.decrypt(ciphertext); return pText; }
复制代码


  方式 2、使用 java cp 命名对加密生成密文


  参数说明:


  • org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI 是 jasypt 提供的一个用于加密的实体类

  • org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI 是 jasypt 提供的一个用于解密的实体类

  • input 表示需要加密的字符串如:密码

  • password 表示本次加密算法使用的秘钥

  • algorithm 表示加密算法的名称。


  特别说明: 通过该种方式获取密文,需要到 maven 仓库下 jasypt-1.9.3.jar 包所在的路径下执行,否则会报找不到对应的主类。


// 加密命令java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input='root' password=abcdef algorithm=PBEWithMD5AndDES
// 解密命令java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringDecryptionCLI input='z4xP29fuY4wF2AJqp1NnoGJxj' password=abcdef algorithm=PBEWithMD5AndDES
复制代码


  方式 3、使用 jasypt-maven 插件生成密文


  该插件是 jasypt 官方提供,在 pom 中添加对应依赖,然后使用 mvn 命令即可执行加解密操作,具体如下:


// 1、在Pom中添加maven插件依赖<plugin>    <groupId>com.github.ulisesbocchio</groupId>    <artifactId>jasypt-maven-plugin</artifactId>    <version>3.0.4</version></plugin>
// 2、加密命令mvn jasypt:encrypt-value -Djasypt.encryptor.password="秘钥的值" -Djasypt.plugin.value="需要加密的敏感信息"
// 解密命令mvn jasypt:decrypt-value -Djasypt.encryptor.password="秘钥的值" -Djasypt.plugin.value="需要解密的密文"
复制代码



四、查看执行结果



使用中的一些坑

  使用过程中遇到了许多不可预估的问题,特意总结出来,方便读者参考。

1、使用 jasypt3.0 启动时报:Failed to bind properties under 'xxx.xxx.xxx' to java.lang.String

  官方描述,3.0 后默认支持的算法为 PBEWITHHMACSHA512ANDAES_256 ,该种加密方式由 sha512 加 AES 高级加密组成,需要 JDK1.9 以上支持或者添加 JCE(Java Cryptography Extension 无限强度权限策略文件)支持,否则运行会出现错误。



  解决方式:


  • 方式 1、将加密算法替换成 PBEWithMD5AndDES 算法,并配置 iv-generator-classname: 为 org.jasypt.iv.NoIvGenerator 值



  • 方式 2、降低 jasypt 的版本 - 使用 2.x 的版本



2、加解密秘钥如何存储

  如果秘钥写在代码或者配置文件,一旦代码泄露,那别人就可以使用秘钥解密我们的密文,这样对敏感信息加密的作用就不存在了,因此,秘钥不能以明文形式存储在代码或者配置文件中,下面就介绍一些安全的存储秘钥的形式。


  方式 1、把秘钥当做程序启动时的命令行参数(推荐),示例如下:


java -jar xxx.jar --jasypt.encryptor.password=秘钥
复制代码


  方式 2、把秘钥当做程序启动时环境变量(推荐),示例如下:


java  -Djasypt.encryptor.password=秘钥 -jar xxx.jar
复制代码


  方式 3、自定义加密、解密器逻辑(这个自定代码,本文不展开讲解,后续有需要重开一篇文章详细讲解)



如何避免 Git 泄露

  因为开发者的疏漏,不小心将源码提交到开源仓库中的新闻不在少数,作为一个开发团队,如何采取一些有效的措施去最小程度防止出现这种情况呢? 除了本文介绍的对敏感信息加密,并合理保存秘钥外,还有以下的一些方式可以参考。


  方式 1、更规范的代码提交、推送制度、培养开发者的安全意识: 很多时候,代码的泄露除了故意为之外,大多数是因为不小心导致,因此在项目中可以通过合理管控权限的方式来防止代码泄露。


  方式 2、合理利用 Git 忽略文件(.gitignore): 通过 gitignore 文件配置匹配规则,最大程度避免敏感信息上传到 Git 仓库。


  方式 3、借助第三方工具,在提交、推送时检测代码是否有敏感数据: 常见的如 git-secrets,在提交前会对变更内容做检测,如果检测到预期的提交内容可能包含敏感信息,那它们将会拒绝提交。


  方式 4、代码的 Code Review: 团队 leader 和成员之间可以互相合作,在代码推送合并时检测是否存在敏感数据,这样不仅可以排查出敏感数据,还能够学习彼此之间的一些编码技巧。



问题探讨

  在编写本篇文章内容时,无意中看到一个消息:Nginx 之父被俄罗斯警方带走,起因是因为其老东家 Rambler 举报 Nginx 是他在就职期间的业务时间进行开发的一个软件,Rambler 认为其应该有该软件代码的所有权。


  针对这一事件大家有什么看法呢?程序员在就职期间的业务时间开发或者编写的项目应该归属于公司?欢迎在文章下留言讨论。



写在最后

  源代码安全在技术企业中意味着竞争力、生命线,一旦泄露,轻则造成项目失败,重则可能导致公司倒闭,这一关检测的重要性不言而喻,作为一名开发者,也应该时刻培养自己的安全意识,在编码时规避掉相应的风险。


  如果文章对你有帮助,欢迎给我点赞、关注。如有疑问,欢迎添加博主进行交流。


发布于: 刚刚阅读数: 3
用户头像

公众号:IT学习日记 2019.11.25 加入

平台:InfoQ&阿里云签约作者,CSDN、头条、知乎、掘金优质创作者,全网粉丝5w+。 领域:专注输出JAVA、数据库、算法等领域干货知识。 微信:yyuuyy1235

评论

发布
暂无评论
拒绝裸奔,SpringBoot集成Jasypt加密敏感信息_jasypt_IT学习日记_InfoQ写作社区