扔掉工具类!MyBatis 一个简单配置搞定加密、解密,不能太方便了~!

开发 后端
介绍一个简单的MyBatis加解密方式,日常学习工作中提及这种方法的比较少,所以拿来说说,如果已经知道这种方法的忽略本文!

一、背景

在我们数据库中有些时候会保存一些用户的敏感信息,比如:手机号、银行卡等信息,如果这些信息以明文的方式保存,那么是不安全的。假如:黑客黑进了数据库,或者离职人员导出了数据,那么就可能导致这些敏感数据的泄漏。因此我们就需要找到一种方法来解决这个问题。

二、解决方案

由于我们系统中使用了Mybatis作为数据库持久层,因此决定使用Mybatis的TypeHandler或Plugin来解决。

TypeHandler :  需要我们在某些列上手动指定 typeHandler 来选择使用那个typeHandler或者根据@MappedJdbcTypes 和 @MappedTypes注解来自行推断。

<result column="phone" property="phone"  
typeHandler="com.huan.study.mybatis.typehandler.EncryptTypeHandler"/>
  • 1.
  • 2.

Plugin : 可以拦截系统中的 select、insert、update、delete等语句,也能获取到sql执行前的参数和执行后的数据。

经过考虑,决定使用TypeHandler来加解密数据。

三、需求

我们有一张客户表customer,里面有客户手机号(phone)和客户地址(address)等字段,其中客户手机号(phone)是需要加密保存到数据库中的。

1、在添加客户信息时,自动将客户手机号加密保存到数据中。

2、在查询客户信息时,自动解密客户手机号。

四、实现思路

1、编写一个实体类,凡是此实体类的数据都表示需要加解密的

public class Encrypt {
   private String value;
   public Encrypt() {
   }
   public Encrypt(String value) {
       this.value = value;
   }
   public String getValue() {
       return value;
   }
   public void setValue(String value) {
       this.value = value;
   }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

2、编写一个加解密的TypeHandler

  •  设置参数时,加密数据。
  •  从数据库获取记录时,解密数据。
package com.huan.study.mybatis.typehandler;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
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.nio.charset.StandardCharsets;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 加解密TypeHandler
*
* @author huan.fu 2021/5/18 - 上午9:20
*/
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(Encrypt.class)
public class EncryptTypeHandler extends BaseTypeHandler<Encrypt> {
   private static final byte[] KEYS = "12345678abcdefgh".getBytes(StandardCharsets.UTF_8);
   /**
    * 设置参数
    */
   @Override
   public void setNonNullParameter(PreparedStatement ps, int i, Encrypt parameter, JdbcType jdbcType) throws SQLException {
       if (parameter == null || parameter.getValue() == null) {
           ps.setString(i, null);
           return;
       }
       AES aes = SecureUtil.aes(KEYS);
       String encrypt = aes.encryptHex(parameter.getValue());
       ps.setString(i, encrypt);
   }
   /**
    * 获取值
    */
   @Override
   public Encrypt getNullableResult(ResultSet rs, String columnName) throws SQLException {
       return decrypt(rs.getString(columnName));
   }
   /**
    * 获取值
    */
   @Override
   public Encrypt getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
       return decrypt(rs.getString(columnIndex));
   }
   /**
    * 获取值
    */
   @Override
   public Encrypt getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
       return decrypt(cs.getString(columnIndex));
   }
   public Encrypt decrypt(String value) {
       if (null == value) {
           return null;
       }
       return new Encrypt(SecureUtil.aes(KEYS).decryptStr(value));
   }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.

注意⚠️:

  •  @MappedTypes:表示该处理器处理的java类型是什么。
  •  @MappedJdbcTypes:表示处理器处理的Jdbc类型。

3、sql语句中写法

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.huan.study.mybatis.mappers.CustomerMapper">
   <resultMap id="BaseResultMapper" type="com.huan.study.mybatis.entity.Customer">
       <id column="id" property="id"/>
       <result column="phone" property="phone"/>
       <result column="address" property="address"/>
   </resultMap>
   <insert id="addCustomer">
       insert into customer(phone,address) values (#{phone},#{address})
   </insert>
   <select id="findCustomer" resultMap="BaseResultMapper">
       select * from customer where phone = #{phone}
   </select>
</mapper>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

SQL中没有什么特殊的写法。

4、配置文件中指定Typehandler的包路径

mybatis.type-handlers-package=com.huan.study.mybatis.typehandler
  • 1.

5、编写后台代码

  •  提供一个添加方法
  •  提供一个根据手机号查询的方法

后台代码比较简单,直接查看:

  •  https://gitee.com/huan1993/spring-cloud-parent/tree/master/mybatis/mybatis-typehandler-encrypt

贴一个mapper层的截图。

6、测试结果

从测试结果中可知,添加数据时,需要加密的数据(phone)在数据库中已经加密了,在查询的时候,加密的数据已经自动解密了。

五、实现代码

  •  https://gitee.com/huan1993/spring-cloud-parent/tree/master/mybatis/mybatis-typehandler-encrypt
责任编辑:庞桂玉 来源: Java后端技术
相关推荐

2022-03-24 09:13:54

Mybatis加密解密

2025-03-03 00:00:55

Spring文件下载开发

2011-04-12 14:58:23

加密解密类

2024-09-27 15:24:15

Spring数据加解密

2022-07-15 14:26:36

开源工具IP

2021-09-24 15:00:26

微信PC电脑移动应用

2011-03-24 09:34:41

SPRING

2021-09-24 09:59:59

复制粘贴PythonPDF

2022-11-08 15:14:17

MyBatis插件

2019-07-24 10:50:56

Python 开发编程语言

2021-02-08 11:46:17

Python自动化邮件

2024-03-01 09:58:44

2022-06-23 08:42:08

配置加密解密

2024-04-15 00:00:02

OpenAI模型性能

2012-07-17 17:05:55

JavaScript

2022-01-26 15:20:00

配置微服务架构

2011-06-17 16:49:05

Cocoa苹果

2009-07-07 11:38:54

jsp oracle

2020-07-20 10:00:52

Python翻译工具命令行

2024-02-04 19:15:09

Nest.js管理项目
点赞
收藏

51CTO技术栈公众号