微服务SpringBoot整合Jasypt加密工具

简介: 微服务SpringBoot整合Jasypt加密工具

正文


一、Jasypt介绍


Jasypt是Java加密工具包,能支持对密码的哈希加密,对文本和二进制数据的对称加解密,还能集成SpringBoot项目对配置文件中的密钥进行加密存储。


引入依赖如下:

<!-- https://mvnrepository.com/artifact/com.github.ulisesbocchio/jasypt-spring-boot-starter -->
<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>3.0.4</version>
</dependency>


二、Jasypt手动使用


2.1 密码加密场景


用户注册账户的时候需要输入密码,我们将密码加密后保存到数据库中,保证用户的敏感数据的安全性。当用户再次登录的时候,我们需要将登录密码和注册时保存的密文密码进行比对,只有比对一致才能完成登录。


密码加密工具类主要有三个,它们都是实现了PasswordEncryptor接口,下面我们逐步来看。

@Slf4j
@RestController
public class SignController {
    private final BasicPasswordEncryptor basicPasswordEncryptor = new BasicPasswordEncryptor();
    private String encryptedPassword = null;
    @GetMapping("/signup/{password}")
    public String signup(@PathVariable String password){
        log.info("用户注册密码为:{}", password);
        encryptedPassword = basicPasswordEncryptor.encryptPassword(password);
        log.info("用户注册密码加密后为:{}", encryptedPassword);
        return encryptedPassword;
    }
    @GetMapping("/signin/{password}")
    public String signin(@PathVariable String password){
        log.info("用户登录密码为:{}", password);
        if(basicPasswordEncryptor.checkPassword(password, encryptedPassword)){
            log.info("用户登录成功!");
            return "success";
        }
        log.info("用户登录失败!");
        return "fail";
    }
}

启动项目后,我们首先注册用户密码localhost:8080/signup/123456,就能得到密文5b32ygn5pbBvphjIKco6X8Z2VfWqwEUw,并将其保存到类变量中暂存,当我们再次登录localhost:8080/signin/123456,就能登录成功了。相反的,如果登录时密码随意输错,就会登录失败。

2022-10-11 15:41:57.038  INFO 26268 --- [nio-8080-exec-1] c.e.myapp.controller.SignController      : 用户注册密码为:123456
2022-10-11 15:41:57.039  INFO 26268 --- [nio-8080-exec-1] c.e.myapp.controller.SignController      : 用户注册密码加密后为:5b32ygn5pbBvphjIKco6X8Z2VfWqwEUw
2022-10-11 15:42:07.405  INFO 26268 --- [nio-8080-exec-3] c.e.myapp.controller.SignController      : 用户登录密码为:123456
2022-10-11 15:42:07.406  INFO 26268 --- [nio-8080-exec-3] c.e.myapp.controller.SignController      : 用户登录成功!
2022-10-11 15:42:12.767  INFO 26268 --- [nio-8080-exec-4] c.e.myapp.controller.SignController      : 用户登录密码为:123457
2022-10-11 15:42:12.767  INFO 26268 --- [nio-8080-exec-4] c.e.myapp.controller.SignController      : 用户登录失败!

那么这种加密方式是什么呢?我们可以打开BasicPasswordEncryptor的源码,看到类上面的注释:

  • Algorithm: MD5.
  • Salt size: 8 bytes.
  • Iterations: 1000.

意思就是使用的MD5这种哈希算法,并且使用8字节(64位)的盐值,迭代计算1000次得到的密文。


除了使用如上的BasicPasswordEncryptor工具之外,还有StrongPasswordEncryptor工具类,它的加密登记更加的安全:

  • Algorithm: SHA-256.
  • Salt size: 16 bytes.
  • Iterations: 100000.

如果这些加密算法都不能满足你的要求,就可以使用ConfigurablePasswordEncryptor来自定义加密工具类ConfigurablePasswordEncryptor,可以设置自己需要使用的算法。


总结:


接口类PasswordEncryptor主要有如下三个实现类:

  • BasicPasswordEncryptor,使用MD5算法;
  • StrongPasswordEncryptor,使用SHA-256算法;
  • ConfigurablePasswordEncryptor,可自定义指定哈希算法;

哈希算法是不可逆的,因此只有加密encryptPassword和检查checkPassword两个方法。


2.2 文本加密场景


用户的手机号、身份证号等敏感信息在存储的时候需要进行加密,但是这些敏感数据在需要使用的时候是需要明文解密的,因此不适合使用2.1节的哈希算法,而是使用对称加密的形式。


文本加密工具类主要有三个,它们都是实现了TextEncryptor接口,下面我们逐步来看。

@Slf4j
@RestController
public class TextController {
    private static final BasicTextEncryptor basicTextEncryptor = new BasicTextEncryptor();
    private static final String SECRET = "hello";
    private String encryptedText = null;
    static {
        basicTextEncryptor.setPassword(SECRET);
    }
    @GetMapping("/encryptText/{plainText}")
    public String encryptText(@PathVariable String plainText){
        log.info("用户输入明文:{}", plainText);
        encryptedText = basicTextEncryptor.encrypt(plainText);
        log.info("用户加密密文:{}", encryptedText);
        return encryptedText;
    }
    @GetMapping("/decryptText")
    public String decryptText(){
        String plainText = basicTextEncryptor.decrypt(encryptedText);
        log.info("用户原始明文:{}", plainText);
        return plainText;
    }
}

项目启动后,我们分别访问localhost:8080/encryptText/hello进行加密,访问localhost:8080/decryptText进行解密。

2022-10-11 15:52:36.949  INFO 21652 --- [nio-8080-exec-1] c.e.myapp.controller.TextController      : 用户输入明文:hello
2022-10-11 15:52:36.950  INFO 21652 --- [nio-8080-exec-1] c.e.myapp.controller.TextController      : 用户加密密文:u/qYluhyFpyOA6xMD3z3JA==
2022-10-11 15:52:46.345  INFO 21652 --- [nio-8080-exec-2] c.e.myapp.controller.TextController      : 用户原始明文:hello


我们同样打开BasicTextEncryptor可以看到它的加密原理:

  • Algorithm: PBEWithMD5AndDES.
  • Key obtention iterations: 1000.


同样的,我们可以使用安全性更高的StrongTextEncryptor:

  • Algorithm: PBEWithMD5AndTripleDES.
  • Key obtention iterations: 1000.


还有安全性更高的AES256TextEncryptor:

  • Algorithm: PBEWithHMACSHA512AndAES_256".
  • Key obtention iterations: 1000.

2.3 数值加密场景


如果需要对整数或者小数进行加密,就可以分别使用IntegerNumberEncryptor接口和DecimalNumberEncryptor接口的实现类。同样的,这种场景的加密也都是对称加密,用法完全一样。


IntegerNumberEncryptor:主要用来对整数进行加解密。


  • BasicIntegerNumberEncryptor

Algorithm: PBEWithMD5AndDES.

Key obtention iterations: 1000.

  • StrongIntegerNumberEncryptor

Algorithm: PBEWithMD5AndTripleDES.

Key obtention iterations: 1000.

  • AES256IntegerNumberEncryptor

Algorithm: PBEWithHMACSHA512AndAES_256.

Key obtention iterations: 1000.


DecimalNumberEncryptor:主要用来对小数进行加解密。


  • BasicDecimalNumberEncryptor

Algorithm: PBEWithMD5AndDES.

Key obtention iterations: 1000

  • StrongDecimalNumberEncryptor

Algorithm: PBEWithMD5AndTripleDES.

Key obtention iterations: 1000.

  • AES256DecimalNumberEncryptor

Algorithm: PBEWithHMACSHA512AndAES_256.

Key obtention iterations: 1000.


2.4 二进制数据加密场景


暂未遇到需要加密二进制数据的业务场景,此处略过,使用方法可以参考官网。


三、Jasypt整合SpringBoot


SpringBoot应用中有很多密钥和密码都是存储在配置文件中的,我们需要将它们以密文的方式存储起来。

# 服务器配置
server:
  port: 8080
# Spring配置
spring:
  # 数据源配置
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?characterEncoding=utf-8&&serverTimezone=Asia/Shanghai&&useSSL=false
    username: root
    # 此处是密码的密文,要用ENC()进行包裹
    password: ENC(KZeGx0ixuy4UrBp1HuhiDNnKB0cJr0cW)
# mybatis配置
mybatis:
  mapper-locations: classpath:mapper/*Mapper.xml
# 加密配置
jasypt:
  encryptor:
    # 指定加密密钥,生产环境请放到启动参数里面
    password: your-secret
    # 指定解密算法,需要和加密时使用的算法一致
    algorithm: PBEWithMD5AndDES
    # 指定initialization vector类型
    iv-generator-classname: org.jasypt.iv.NoIvGenerator


如上是对数据库密码进行加密存储,密文是怎么的来的?可以写一个测试类,使用第二节介绍的内容自己手动加密。

@Slf4j
public final class JasyptUtils {
    /**
     * 加密使用密钥
     */
    private static final String PRIVATE_KEY = "lybgeek";
    private static BasicTextEncryptor basicTextEncryptor = new BasicTextEncryptor();
    static {
        basicTextEncryptor.setPassword(PRIVATE_KEY);
    }
    /**
     * 私有构造方法,防止被意外实例化
     */
    private JasyptUtils() {
    }
    /**
     * 明文加密
     *
     * @param plaintext 明文
     * @return String
     */
    public static String encrypt(String plaintext) {
        log.info("明文字符串为:{}", plaintext);
        // 使用的加密算法参考2.2节内容,也可以在源码的类注释中看到
        String ciphertext = basicTextEncryptor.encrypt(plaintext);
        log.info("密文字符串为:{}", ciphertext);
        return ciphertext;
    }
    /**
     * 解密
     *
     * @param ciphertext 密文
     * @return String
     */
    public static String decrypt(String ciphertext) {
        log.info("密文字符串为:{}", ciphertext);
        ciphertext = "ENC(" + ciphertext + ")";
        if (PropertyValueEncryptionUtils.isEncryptedValue(ciphertext)) {
            String plaintext = PropertyValueEncryptionUtils.decrypt(ciphertext, basicTextEncryptor);
            log.info("明文字符串为:{}", plaintext);
            return plaintext;
        }
        log.error("解密失败!");
        return "";
    }
}
@Slf4j
public class JasyptUtilsTest {
    @Test
    public void testEncrypt(){
        String plainText = "Glrs@1234";
        String ciperText = JasyptUtils.encrypt(plainText);
        log.info("加密后的密文为:{}", ciperText);
    }
    @Test
    public void testDecrypt(){
        String ciperText = "KZeGx0ixuy4UrBp1HuhiDNnKB0cJr0cW";
        String plainText = JasyptUtils.decrypt(ciperText);
        log.info("解密后的明文为:{}", plainText);
    }
}

经过如上的配置,启动项目,如下从数据库获取数据的应用逻辑就能正常使用了。

@Slf4j
@RestController
public class HelloController {
    @Autowired
    UserMapper userMapper;
    @GetMapping("/getHello")
    public String getHello(){
        log.info("myapp works!");
        List<User> users = userMapper.listUsers();
        return users.toString();
    }
}
@Mapper
public interface UserMapper {
    List<User> listUsers();
}
<mapper namespace="com.example.myapp.mapper.UserMapper">
    <select id="listUsers" resultType="com.example.myapp.bean.User">
        select zu.user_id userId, zu.user_name userName, zu.age age, zu.user_email userEmail from zx_user zu;
    </select>
</mapper>


四、生成环境启动


生产环境密钥作为启动参数:

java -jar -Djasypt.encryptor.password=your-secret


五、参考文档


Jasypt: Java simplified encryption - Jasypt: Java simplified encryption - Mainhttps://links.jianshu.com/go?to=http%3A%2F%2Fwww.jasypt.org%2F


相关文章
运维 监控 数据可视化
334 1
|
8月前
|
安全 算法 Java
在Spring Boot中应用Jasypt以加密配置信息。
通过以上步骤,可以在Spring Boot应用中有效地利用Jasypt对配置信息进行加密,这样即使配置文件被泄露,其中的敏感信息也不会直接暴露给攻击者。这是一种在不牺牲操作复杂度的情况下提升应用安全性的简便方法。
1376 10
|
9月前
|
人工智能 安全 Java
Spring Boot yml 配置敏感信息加密
本文介绍了如何在 Spring Boot 项目中使用 Jasypt 实现配置文件加密,包含添加依赖、配置密钥、生成加密值、在配置中使用加密值及验证步骤,并提供了注意事项,确保敏感信息的安全管理。
1490 1
|
10月前
|
安全 Java 数据库
Jasypt加密数据库配置信息
本文介绍了使用 Jasypt 对配置文件中的公网数据库认证信息进行加密的方法,以提升系统安全性。主要内容包括:1. 背景介绍;2. 前期准备,如依赖导入及版本选择;3. 生成密钥并实现加解密测试;4. 在配置文件中应用加密后的密码,并通过测试接口验证解密结果。确保密码安全的同时,保障系统的正常运行。
698 3
Jasypt加密数据库配置信息
|
11月前
|
数据采集 监控 API
加密货币 Pump 监测刮刀工具开发原理及实现路径
开发Pump监测刮刀工具需综合运用高频数据采集、波动率建模、跨平台对冲三大核心技术,2025年的技术瓶颈已从基础数据获取转向超低延迟执行与合规适配。建议采用模块化开发策略,优先实现核心监控功能,再逐步接入AI决策与链上套利模块。代码示例需根据最新交易所API文档动态调整,并严格遵守所在地监管法规。
|
安全 Java Apache
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 身份和权限认证
本文介绍了 Apache Shiro 的身份认证与权限认证机制。在身份认证部分,分析了 Shiro 的认证流程,包括应用程序调用 `Subject.login(token)` 方法、SecurityManager 接管认证以及通过 Realm 进行具体的安全验证。权限认证部分阐述了权限(permission)、角色(role)和用户(user)三者的关系,其中用户可拥有多个角色,角色则对应不同的权限组合,例如普通用户仅能查看或添加信息,而管理员可执行所有操作。
608 0
|
安全 Java 数据安全/隐私保护
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 三大核心组件
本课程介绍如何在Spring Boot中集成Shiro框架,主要讲解Shiro的认证与授权功能。Shiro是一个简单易用的Java安全框架,用于认证、授权、加密和会话管理等。其核心组件包括Subject(认证主体)、SecurityManager(安全管理员)和Realm(域)。Subject负责身份认证,包含Principals(身份)和Credentials(凭证);SecurityManager是架构核心,协调内部组件运作;Realm则是连接Shiro与应用数据的桥梁,用于访问用户账户及权限信息。通过学习,您将掌握Shiro的基本原理及其在项目中的应用。
459 0
|
消息中间件 Java 微服务
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——发布/订阅消息的生产和消费
本文详细讲解了Spring Boot中ActiveMQ的发布/订阅消息机制,包括消息生产和消费的具体实现方式。生产端通过`sendMessage`方法发送订阅消息,消费端则需配置`application.yml`或自定义工厂以支持topic消息监听。为解决点对点与发布/订阅消息兼容问题,可通过设置`containerFactory`实现两者共存。最后,文章还提供了测试方法及总结,帮助读者掌握ActiveMQ在异步消息处理中的应用。
535 0
|
消息中间件 网络协议 Java
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——ActiveMQ集成
本文介绍了在 Spring Boot 中集成 ActiveMQ 的详细步骤。首先通过引入 `spring-boot-starter-activemq` 依赖并配置 `application.yml` 文件实现基本设置。接着,创建 Queue 和 Topic 消息类型,分别使用 `ActiveMQQueue` 和 `ActiveMQTopic` 类完成配置。随后,利用 `JmsMessagingTemplate` 实现消息发送功能,并通过 Controller 和监听器实现点对点消息的生产和消费。最后,通过浏览器访问测试接口验证消息传递的成功性。
850 0
|
消息中间件 存储 Java
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——ActiveMQ安装
本教程介绍ActiveMQ的安装与基本使用。首先从官网下载apache-activemq-5.15.3版本,解压后即可完成安装,非常便捷。启动时进入解压目录下的bin文件夹,根据系统选择win32或win64,运行activemq.bat启动服务。通过浏览器访问`http://127.0.0.1:8161/admin/`可进入管理界面,默认用户名密码为admin/admin。ActiveMQ支持两种消息模式:点对点(Queue)和发布/订阅(Topic)。前者确保每条消息仅被一个消费者消费,后者允许多个消费者同时接收相同消息。
466 0
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——ActiveMQ安装