java实现MySQL数据加密存储---自定义mybatis处理器+mybatisplus注解

需求 敏感字段需要加密储存到数据库 例如姓名 电话 身份证 银行卡等

先看效果

 这里是会员表 对会员卡号 姓名  身份证号 手机号 邮箱做了加密处理

思路

1.自定义类型处理器  

  1.1 继承MyBatis框架 抽象类BaseTypeHandler

  1.2 重写四个方法 实现自己的加密逻辑 这里使用AES加密

2.定义实体类

  2.1 使用MyBatis-Plus 注解@TableName 增加属性设置 autoResultMap=true

  2.2 使用MyBatis-Plus 注解@TableField 在要加密的字段设置 typeHandler=自定义的类型处理器

说明  字段加上@TableField(typeHandler = AESEncryptHandler.class) 就可以实现你的加密逻辑了

开始操作

自定义类型处理器  
public class AESEncryptHandler extends BaseTypeHandler {

    private final  String password = "VtW*******1w==";

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, AESUtil.encrypt((String)parameter, password));
    }
    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String columnValue = rs.getString(columnName);
        return AESUtil.decrypt(columnValue, password);
    }
    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String columnValue = rs.getString(columnIndex);
        return AESUtil.decrypt(columnValue, password);
    }
    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String columnValue = cs.getString(columnIndex);
        return AESUtil.decrypt(columnValue, password);
    }
}

 AES工具类

public class AESUtil {

        private static final String KEY_ALGORITHM = "AES";
    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";//默认的加密算
    
    /**
     * AES 加密操作
     *
     * @param content
     * @param password
     * @return
     */
    public static String encrypt(String content, String password) {
        try {
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);

            byte[] byteContent = content.getBytes("utf-8");

            cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(password));// 初始化为加密模式的密码器

            byte[] result = cipher.doFinal(byteContent);// 加密

            return Base64.getEncoder().encodeToString(result);//通过Base64转码返回
        } catch (Exception ex) {
            Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
        }

        return null;
    }

    /**
     * AES 解密操作
     *
     * @param content
     * @param password
     * @return
     */
    public static String decrypt(String content, String password) {

        try {
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);

            cipher.init(Cipher.DECRYPT_MODE, getSecretKey(password));

            //执行操作
            byte[] result = cipher.doFinal(Base64.getDecoder().decode(content));

            return new String(result, "utf-8");
        } catch (Exception ex) {
//            log.error(ex.getMessage(),ex);
        }

        return null;
    }
}

实体类

/**
 * 会员卡表
 * @TableName vip_card
 */
@TableName(value ="vip_card",autoResultMap = true)
@Data
public class VipCard implements Serializable {
    /**
     * id
     */
    @TableId(type = IdType.AUTO)
    private Integer id;

    /**
     * 卡号
     */
    @TableField(typeHandler = AESEncryptHandler.class)
    private String cardNo;

    /**
     * 用户名
     */
    @TableField(typeHandler = AESEncryptHandler.class)
    private String name;

    /**
     * 性别
     */
    private Integer gender;

    /**
     * 年龄
     */
    private Integer age;

    /**
     * 邮箱
     */
    private String email;

    /**
     * 身份证号
     */
    @TableField(typeHandler = AESEncryptHandler.class)
    private String idNumber;

    /**
     * 手机号
     */
    @TableField(typeHandler = AESEncryptHandler.class)
    private String phoneNumber;

    /**
     * 创建时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="Asia/Shanghai")
    private Date createTime;

    /**
     * 更新时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="Asia/Shanghai")
    private Date updateTime;

测试类

@SpringBootTest
class SecuritydemoApplicationTests {

    @Resource
    VipCardMapper vipCardMapper;
    
    private final static String password = "Vt**********1w==";

    @Test
    void add() {
        VipCard vipCard = new VipCard();
        vipCard.setCardNo("6222********99950");
        vipCard.setGender(0);
        vipCard.setName("赵三");
        vipCard.setEmail("666666@166.com");
        vipCard.setIdNumber("4101********0160");
        vipCard.setAge(19);
        vipCard.setPhoneNumber("136*****30");
        vipCard.setCreateTime(new Date());
        vipCard.setUpdateTime(new Date());
        System.out.println("新增数据>>>>>>>>>>>>>>>>>> " + vipCardMapper.insert(vipCard));
    }

    @Test
    void one() {
        VipCard vipCard = vipCardMapper.selectById(8);
        System.out.println("查询一条>>>>>>>>>>>>>>>>>>  " + vipCard);
    }

    @Test
    void list() {
        List<VipCard> vipCardList = vipCardMapper.selectList(null);
        System.out.println("查询列表>>>>>>>>>>>>>>>>>> " + vipCardList);
    }

    @Test
    void listByCondition() {
        QueryWrapper<VipCard> queryWrapper = new QueryWrapper<>();

        String Mname = AESUtil.encrypt("赵六六", password);
        queryWrapper.eq("name", Mname)
                    .eq("age", 18)
                    .eq("gender",0);
        List<VipCard> vipCardList = vipCardMapper.selectList(queryWrapper);
        System.out.println("查询列表>>>>>>>>>>>>>>>>>>  " + vipCardList);
    }
    


    @Test
    void update() {
        VipCard vipCard = new VipCard();
        vipCard.setEmail("666666@163.com");
        vipCard.setPhoneNumber("13666666666");

        UpdateWrapper<VipCard> updateWrapper  = new UpdateWrapper();
        String Mname = AESUtil.encrypt("赵六六", password);
        updateWrapper.eq("name", Mname);
        int update = vipCardMapper.update(vipCard, updateWrapper);
        System.out.println("更新>>>>>>>>>>>>>>>>>> " + update);
    }


    @Test
    void del(){
        Map<String,Object> map = new HashMap<>();
        String Mname = AESUtil.encrypt("赵六六", password);
        map.put("name",Mname);
        int i = vipCardMapper.deleteByMap(map);
        System.out.println("删除>>>>>>>>>>>>>>>>>> " + i);
    }

    @Test
    void del2(){
        String McardNo = AESUtil.encrypt("622202170289999995911", password);
        QueryWrapper<VipCard> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("card_no", McardNo);
        int i = vipCardMapper.delete(queryWrapper);
        System.out.println("删除>>>>>>>>>>>>>>>>>> " + i);
    }
    
}

 说明  后台程序在查询数据会自动解密  查询的条件要先进行加密  不然查出来为null  因为此时入库的数据都是加密过的    不加密无法匹配数据

最后来看下

MyBatis内置类型处理器

mybatis为我们实现了那么多TypeHandler

本文就是继承了抽象类BaseTypeHandler 实现了AES加密

古人学问无遗力,少壮工夫老始成。 纸上得来终觉浅,绝知此事要躬行。
原文地址:https://www.cnblogs.com/wf-zhang/p/14842403.html