使用Mybatis 的TypeHandler对敏感数据进行加密解密操作!

项目负责人原本是想把敏感数据加密放到项目收尾的时候做的。但是在项目中后期的时候,来了网警来查看数据库信息。发现数据库没有加密然后要求我们该项目要立刻把敏感数据(例如:手机号、身份证号、居住地址、)加密

public class AESEncryptionTypeHandler extends BaseTypeHandler<String> {
    private SecretKeySpec secretKeySpec;
    private IvParameterSpec ivParameterSpec;
 
public AESEncryptionTypeHandler() {
    this(
       // 256 bits 密钥(自己设定)
       Optional.ofNullable(System.getenv("DB_ENCRYPTION_SECRET_KEY")).orElse("密钥"),
      // 128 bits 初始向量(自己设定)
       Optional.ofNullable(System.getenv("DB_ENCRYPTION_IV")).orElse("初始向量")
     );
}
//设置密钥规格 以及 参数说明
public AESEncryptionTypeHandler(String secretKey, String iv) {
    if (secretKey != null) {
        secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "AES");
        ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
    }
}
// 数据加密
public String encrypt(String plainText) throws GeneralSecurityException {
    if (secretKeySpec == null) {
        return plainText;
    }
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
    byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
    return Base64Utils.encodeToString(encrypted);
}
// 数据解密
public String decrypt(String encrypted) throws GeneralSecurityException {
    if (secretKeySpec == null) {
        return encrypted;
    }
//有坑 =》 如果数据加密后过长 会自动换行 导致解密报错 ->去掉空格和换行
    encrypted = encrypted.replace("\n","");
    encrypted = encrypted.replace("\r","");
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
    cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
    byte[] decryptedBytes = cipher.doFinal(Base64Utils.decodeFromString(encrypted));
    return new String(decryptedBytes, StandardCharsets.UTF_8);
}

@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
    try {
        ps.setString(i, parameter == null ? null : encrypt(parameter));
    } catch (GeneralSecurityException e) {
        throw new RuntimeException(e);
    }
}

private String decryptValue(String value) {
    if (value == null) {
        return null;
    }
    try {
        return decrypt(value);
    } catch (GeneralSecurityException e) {
        throw new RuntimeException(e);
    }
}
  1. 实体类中表名中添加注解并设置autoResultMap=true

@TableName(value = "logininfo",autoResultMap = true)
  1. 在需要加密字段上添加注解

@TableField(value = "phone",typeHandler = AESEncryptionTypeHandler.class)
private String phone;
  1. 如果是该原本实体类的映射只需要在实体类与表的映射Map中添加typeHanlder

<result property="phone" column="userName" typeHandler="com.jeethink.encryption.AESEncryptionTypeHandler"/>
  1. 如果查询SQL中是自己定义的映射对象就需要自己定义该映射对象的ResultMap

<resultMap id="LoginInfoVOMap" type="com.jeethink.user.domain.vo.LoginInfoVO">
 <result property="id" column="id"/>
 <result property="userName" column="userName" typeHandler="com.jeethink.encryption.AESEncryptionTypeHandler"/>
 <result property="phone" column="phone" typeHandler="com.jeethink.encryption.AESEncryptionTypeHandler"/>
</resultMap>
  1. 注意:当加密之后加密字段的查询不能模糊查询了并且在加密数据查询时加密条件需要加上typeHandler

phone = #{phone,typeHandler=com.jeethink.encryption.AESEncryptionTypeHandler}

运用Mybatis的加密相对来说更简单但是会影响查询效率如果数据量比较大建议还是考虑其他加密方法;

还有一个缺陷是这个加密方法当遇到明文或者密钥不同的数据时,会直接报错。

SET block_encryption_mode = 'aes-256-cbc'; //执行加密解密时 必须先执行该语句
SELECT TO_BASE64(AES_ENCRYPT('1234567489', '密钥', '初始向量')),AES_DECRYPT(FROM_BASE64('27ww+0zOkvlwRHihPsL3yw=='), '密钥', '初始向量');

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值