SpringBoot 集成 jasypt 进行数据加解密(2.x与3.x区别)

jasypt简介:Jasypt是一个Java库,允许开发人员以最小的努力将基本的加密功能添加到项目中,而无需深入了解加密协议的实现细节。 

1.目的

对数据库存储的敏感信息,如身份证号、电话号码等进行加解密处理;

对配置文件中的敏感信息,如jdbc账号密码进行加密处理。

2.引入配置

第一种方式前提是持久层采用mybatis框架,如采用其他持久层框架可采用第二种注解方式

2.1 引用jar包

目前通用版本为2.x和3.x 区别

2.x

  1. 所依赖的springboot版本为2.0.0~3.1.0
  2. 默认加密算法 PBEWithMD5AndDES
  3. 默认生成盐的类org.jasypt.salt.RandomSaltGenerator
  4. 默认IV生成器类 org.jasypt.iv.NoIvGenerator

3.x

  1. 所依赖的springboot版本为2.2.1~3.1.0
  2. 默认加密算法 PBEWITHHMACSHA512ANDAES_256
  3. 默认生成盐的类org.jasypt.salt.RandomSaltGenerator
  4. 默认IV生成器类org.jasypt.iv.RandomIvGenerator
	    <dependency>
			<groupId>com.github.ulisesbocchio</groupId>
			<artifactId>jasypt-spring-boot-starter</artifactId>
			<version>3.0.4</version>
		</dependency>

2.2 yml文件配置相关属性

jasypt:
  encryptor:
    # 盐值 需要配置
    password: salt123
    # 指定加密方式 (可以不配置有默认值)
    algorithm: PBEWITHHMACSHA512ANDAES_256
    #设置初始向量IV生成器的类名 (可以不配置有默认值)
    iv-generator-classname: org.jasypt.iv.NoIvGenerator
    property: #(可以不配置 默认为ENC() )
      # 标识为加密属性的前缀
      prefix: ENC(
      # 标识为加密属性的后缀
      suffix: )

3.操作实现(第一种)(相关代码 复制粘贴即可)

第一种方式采用mybatis的类型转换器(TypeHandler)

注意:采用mybatis自带的方法可以直接使用,在属性字段上加入

@TableField(typeHandler = JasyptMybatisHandler.class)即可 

mybatis-plues 则需在实体类上加@TableName(autoResultMap = true) 开启映射注解 

@Component
public class JasyptMybatisHandler implements TypeHandler<String> {


    private final StringEncryptor encryptor;

    public JasyptMybatisHandler(StringEncryptor encryptor) {
        this.encryptor = encryptor;
    }

    @Override
    public void setParameter(PreparedStatement preparedStatement, int i, String s, JdbcType jdbcType) throws SQLException {
        if (StringUtils.isEmpty(s)) {
            preparedStatement.setString(i, "");
        } else {
            preparedStatement.setString(i, encryptor.encrypt(s.trim()));
        }
    }

    @Override
    public String getResult(ResultSet resultSet, String s) throws SQLException {
        if (StringUtils.isEmpty(resultSet.getString(s))) {
            return resultSet.getString(s);
        } else {
            return encryptor.decrypt(resultSet.getString(s).trim());
        }
    }

    @Override
    public String getResult(ResultSet resultSet, int i) throws SQLException {
        if (StringUtils.isEmpty(resultSet.getString(i))) {
            return resultSet.getString(i);
        } else {
            return encryptor.decrypt(resultSet.getString(i).trim());
        }
    }

    @Override
    public String getResult(CallableStatement callableStatement, int i) throws SQLException {
        if (StringUtils.isEmpty(callableStatement.getString(i))) {
            return callableStatement.getString(i);
        } else {
            return encryptor.decrypt(callableStatement.getString(i).trim());
        }
    }
}

4.操作实现 自定义注解

加解密方法注解

@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface JasyptMethod {
  /**
   * 加密enc 解密dec
   */
  String type() default "encrypt";
}

加解密字段注解

@Documented
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface JasyptField {
}

加解密切面 可以自己在优化优化

@Aspect
@Component
@Slf4j
public class JasyptAspect {

  private final StringEncryptor stringEncryptor;

  public JasyptAspect(StringEncryptor stringEncryptor) {
    this.stringEncryptor = stringEncryptor;
  }

  @Pointcut("@annotation(com.beiming.cloud.user.annotation.JasyptMethod)")
  public void pointCut() {
  }

  @Around("pointCut()")
  public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
    JasyptMethod jasyptMethod = methodSignature.getMethod().getAnnotation(JasyptMethod.class);
    String type = jasyptMethod.type();
    Object[] objects = joinPoint.getArgs();
    if (JasyptConstant.ENCRYPT.equalsIgnoreCase(type)) {
      try {
        if (objects.length != 0) {
          for (int i = 0; i < objects.length; i++) {
            if (objects[i] instanceof String) {
              objects[i] = stringEncryptor.encrypt(String.valueOf(objects[i]));
            } else {
              handlerObj(objects[i], JasyptConstant.ENCRYPT, objects[i] instanceof List<?>);
            }
          }
        }
      } catch (Exception e) {
        log.error("TOOLBOX 数据加密失败", e);
      }
    }
    Object obj = joinPoint.proceed(objects);
    if (JasyptConstant.DECRYPT.equalsIgnoreCase(type) && obj != null) {
      if (obj instanceof String) {
        obj = stringEncryptor.decrypt(String.valueOf(obj));
      } else {
        handlerObj(obj, JasyptConstant.DECRYPT, obj instanceof List);
      }
    }
    return obj;
  }

  private void handlerObj(Object obj, String type, boolean isList) {
    if (isList) {
      List<Object> castList = castList(obj, Object.class);
      for (Object o : castList) {
        Field[] fieldList = o.getClass().getDeclaredFields();
        objRun(o, type, fieldList);
      }
    } else {
      Field[] fields = obj.getClass().getDeclaredFields();
      objRun(obj, type, fields);
    }
  }

  private void objRun(Object obj, String type, Field[] fields) {
    for (Field field : fields) {
      boolean hasSecureField = field.isAnnotationPresent(JasyptField.class);
      if (hasSecureField) {
        try {
          //关闭JDK安全检查,提高反射速度
          field.setAccessible(true);
          String realValue = (String) field.get(obj);
          String value;
          if (JasyptConstant.DECRYPT.equals(type)) {
            value = stringEncryptor.decrypt(realValue);
          } else {
            value = stringEncryptor.encrypt(realValue);
          }
          field.set(obj, value);
        } catch (Exception e) {
          log.error("TOOLBOX 反射修改对象属性失败", e);
        }
      }
    }
  }

  public static <T> List<T> castList(Object obj, Class<T> clazz) {
    List<T> result = new ArrayList<T>();
    if (obj instanceof List<?>) {
      for (Object o : (List<?>) obj) {
        result.add(clazz.cast(o));
      }
      return result;
    }
    return null;
  }
}

直接在方法上, 对应实体类加解密字段上配置注解

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Springboot中使用jasypt进行加密的方式有多种。其中一种方式是引入jasypt-spring-boot加密组件,并在工程中设置加密秘钥。首先,需要在pom.xml文件中添加依赖: ```xml <dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>3.0.3</version> </dependency> ``` 接下来,可以通过在应用程序的配置文件(application.properties或application.yml)中设置加密秘钥来实现加密。例如,在application.properties文件中添加以下配置: ``` jasypt.encryptor.password=your_encryption_password ``` 其中"your_encryption_password"是你自己设置的加密密码。这样,加密模块会在应用程序启动时加载秘钥,并使用该秘钥对被加密的数据进行加密和解密操作。 另一种方式是通过脚本的方式进行加密。可以使用jasypt提供的命令行工具来实现加密。例如,在命令行中执行以下命令: ``` java -cp jasypt-1.9.2.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input=your_data password=your_encryption_password algorithm=PBEWithMD5AndDES ``` 其中"your_data"是待加密的内容,"your_encryption_password"是你自己设置的加密密码,"algorithm"是加密算法。执行该命令后,会输出加密后的结果。 总之,Springboot中使用jasypt进行加密可以通过引入jasypt-spring-boot加密组件并设置加密秘钥,或者通过脚本的方式实现加密。<span class="em">1</span><span class="em">2</span><span class="em">3</span>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值