背??景在我们的数据库中,有时会保存一些用户的敏感信息,比如手机号、银行卡等信息。如果此信息以纯文本形式存储,则不安全。如果:黑客入侵数据库,或前员工导出数据,都可能导致这些敏感数据的泄露。所以我们需要想办法解决这个问题。解决方案由于我们系统中使用Mybatis作为数据库持久层,所以我们决定使用Mybatis的TypeHandler或者Plugin来解决。TypeHandler:我们需要在某些列上手动指定typeHandler来选择使用哪个typeHandler或者根据@MappedJdbcTypes和@MappedTypes注解自行推断。Plugin:可以拦截系统中的select、insert、update、delete等语句,并可以还获取sql执行前的参数和执行后的数据。经过考虑,决定使用TypeHandler来加解密数据。需求我们有一个客户表customer,其中包含客户电话号码(phone)和客户地址(address)等字段,其中客户电话号码(phone)需要加密存储在数据库中。1、添加客户信息时,客户手机号码自动加密存储在数据中。2、查询客户信息时,自动解密客户手机号。实现思路1.写一个实体类。该实体类中的所有数据表示publicclassEncrypt{privateStringvalue;publicEncrypt(){}publicEncrypt(Stringvalue){this.value=value;}publicStringgetValue(){返回值;}publicvoidsetValue(Stringvalue){this.value=value;}}2.写加解密TypeHandler时设置参数,加密数据。从数据库中获取记录时,解密数据。包com.huan.study.mybatis.typehandler;导入cn.hutool.crypto.SecureUtil;导入cn.hutool.crypto.symmetric.AES;导入org.apache.ibatis.type.BaseTypeHandler;导入org.apache.ibatis.type.JdbcType;导入org.apache.ibatis.type.MappedJdbcTypes;导入org.apache.ibatis.type.MappedTypes;导入java.nio.charset.StandardCharsets;导入java.sql.CallableStatement;导入java.sql.PreparedStatement;导入java.sql.ResultSet;importjava.sql.SQLException;/***加解密TypeHandler**@authorhuan.fu2021/5/18-上午9:20*/@MappedJdbcTypes(JdbcType.VARCHAR)@MappedTypes(Encrypt.class)publicclassEncryptTypeHandlerextendsBaseTypeHandler{privatestaticfinalbyte[]KEYS="12345678abcdefgh".getBytes(StandardCharsets.UTF_8);/***设置参数*/@OverridepublicvoidsetNonNullParameter(PreparedStatementps,inti,Encryptparameter,JdbcTypejdbcType)throwsSQLException{if(parameter==null||parameter.getValue()==null){ps.setString(i,null);返回;}AESaes=SecureUtil.aes(KEYS);Stringencrypt=aes.encryptHex(parameter.getValue());ps.setString(i,加密);}/***获取价值*/@OverridepublicEncryptgetNullableResult(ResultSetrs,StringcolumnName)throwsSQLException{returndecrypt(rs.getString(columnName));}/***获取价值*/@OverridepublicEncryptgetNullableResult(ResultSetrs,intcolumnIndex)throwsSQLException{returndecrypt(rs.getString(columnIndex));}/***获取价值*/@OverridepublicEncryptgetNullableResult(CallableStatementcs,intcolumnIndex)throwsSQLException{returndecrypt(cs.getString(columnIndex));}publicEncryptdecrypt(Stringvalue){if(null==value){returnnull;}returnnewEncrypt(SecureUtil.aes(KEYS).decryptStr(value));}}注意??:@MappedTypes:表示该处理器Whatisthejavatypeprocessed@MappedJdbcTypes:表示处理器处理的Jdbc类型。3.sql语句中insertintocustomer(phone,address)values(#{phone},#{address})选择*fromcustomerwherephone=#{phone}SQL中没有特殊的写法。4.在配置文件mybatis.type-handlers-package=com.huan.study.mybatis.typehandler中指定Typehandler的包路径5.编写后台代码,提供添加方法,提供基于手机的查询方法数字。后台代码比较简单,可以直接查看:https://gitee.com/huan1993/spring-cloud-parent/tree/master/mybatis/mybatis-typehandler-encrypt贴一张mapper层的截图。6、测试结果从测试结果可以看出,添加数据时,需要加密的数据(手机)已经在数据库中加密,查询时,加密数据已经自动解密。实现代码后台代码:https://gitee.com/huan1993/spring-cloud-parent/tree/master/mybatis/mybatis-typehandler-encrypt