zoukankan      html  css  js  c++  java
  • 使用mybatis的BaseTypeHandler来给敏感字段进行AES加密

    开发中,公司会要求对敏感字段进行加密处理后入库,查询的时候需要解密后展示,这就要求原字符串和加密字符串之间进行转换

    如果一两个字符串还好,可以直接在入库的时候和查询的时候处理一下,但是如果有很多字段都需要这样处理怎么办?

    Mybatis里面有一个TypeHandler可以解决这个问题,只需要在需要加密/解密的字段上使用@TableField(typeHandler = AesTypeHandler.class),

    包含该字段的实体上使用@TableName(autoResultMap = true)即可(PS:AesTypeHandler是自定义的TypeHandler)

    为了方便,这里我们使用的是Hutool的AES加密工具

    首先导入依赖

     <dependency>
           <groupId>cn.hutool</groupId>
           <artifactId>hutool-all</artifactId>
           <version>5.5.8</version>
     </dependency>

    然后创建AesUtil加密工具

    package com.qjc.utils;
    
    import cn.hutool.core.util.HexUtil;
    import cn.hutool.crypto.SecureUtil;
    import org.apache.commons.lang3.StringUtils;
    
    public class AESUtil {
        private static final String AES_KEY = "AES_KEY";
    
        private static final byte[] KEY_BYTES;
    
        private static String keyStr = "ad1725339b2dd0a68903c57b635942ca";
    
        static {
            KEY_BYTES = new byte[16];
            int i = 0;
            for (byte b : keyStr.getBytes()) {
                KEY_BYTES[i++ % 16] ^= b;
            }
        }
    
        public static String encrypt(String content) {
            if (StringUtils.isBlank(content)) {
                return content;
            }
            return HexUtil.encodeHexStr(SecureUtil.aes(KEY_BYTES).encrypt(content), false);
        }
    
        public static String decrypt(String content) {
            if (StringUtils.isBlank(content)) {
                return content;
            }
            return SecureUtil.aes(KEY_BYTES).decryptStr(content);
        }
    
        public static void main(String[] args) {
            String encrypted = encrypt("测试");
            System.out.println(encrypted);
            System.out.println(decrypt(encrypted));
        }
    }

    定义AesTypeHandler

    package com.qjc.config;
    
    import com.baomidou.mybatisplus.core.toolkit.StringUtils;
    import com.qjc.utils.AESUtil;
    import org.apache.ibatis.type.BaseTypeHandler;
    import org.apache.ibatis.type.JdbcType;
    import org.apache.ibatis.type.MappedJdbcTypes;
    import org.apache.ibatis.type.MappedTypes;
    
    import java.sql.CallableStatement;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    /** 数据库中的数据类型 */
    @MappedJdbcTypes(JdbcType.VARCHAR)
    /** 处理后的数据类型 */
    @MappedTypes(value = String.class)
    public class AesTypeHandler extends BaseTypeHandler {
    
        @Override
        public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
            ps.setString(i, AESUtil.encrypt((String) parameter));
        }
    
        @Override
        public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
            return StringUtils.isBlank(rs.getString(columnName)) ? rs.getString(columnName) : AESUtil.decrypt(rs.getString(columnName));
        }
    
        @Override
        public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
            return StringUtils.isBlank(rs.getString(columnIndex)) ? rs.getString(columnIndex) : AESUtil.decrypt(rs.getString(columnIndex));
        }
    
        @Override
        public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
            return StringUtils.isBlank(cs.getString(columnIndex)) ? cs.getString(columnIndex) : AESUtil.decrypt(cs.getString(columnIndex));
        }
    }

    然后再实体和字段上添加注解

    package com.qjc.entity;
    
    import com.baomidou.mybatisplus.annotation.TableField;
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    import com.baomidou.mybatisplus.extension.activerecord.Model;
    
    import java.time.LocalDateTime;
    
    import com.qjc.config.AesTypeHandler;
    import lombok.Data;
    import lombok.EqualsAndHashCode;
    
    
    @Data
    @EqualsAndHashCode(callSuper = true)
    @TableName(value = "t_user", autoResultMap = true)
    public class TUser extends Model {
    
        private static final long serialVersionUID = 1L;
    
        @TableId("id")
        private Long id;
    
        @TableField(typeHandler = AesTypeHandler.class)
        private String name;
    
        private String address;
    
        private Integer age;
    
        private LocalDateTime createTime;
    
        private LocalDateTime updateTime;
    
    
    }

    测试

    @Test
        public void test() {
            TUser user = new TUser();
            user.setName("用户");
            user.setAge(18);
            user.setAddress("地址");
            userMapper.insert(user);
        }

    插入数据

     查询数据

    mysql中直接用HEX(AES_ENCRYPT(str,key_str))函数生成加密串就行,和工具AESUtil生成的加密串是一致的。mysql中解密AES字符串AES_DECRYPT(UNHEX(str),key_str)

    劈天造陆,开辟属于自己的天地!!!与君共勉
  • 相关阅读:
    GAN对抗神经网络(原理解析)
    Wasserstein distance(EM距离)
    浅谈KL散度
    深度学习中 Batch Normalization是什么
    Batch Normalization的正确打开方式
    对于梯度消失和梯度爆炸的理解
    [转贴]loadrunner 场景设计-添加Unix、Linux Resources计数器
    Volley(四)—— ImageLoader & NetworkImageView
    SQL单表查询
    ifconfig命令详解
  • 原文地址:https://www.cnblogs.com/java-spring/p/14676670.html
Copyright © 2011-2022 走看看