Mybatis 字段加解密

需求场景:
当数据库中保存的部分数据需要加密,页面需要解密正常显示。比如手机号码,email,身份证号码等隐私信息。项目开发中对表字段加密解密,业务代码无需关心加解密环节。
解决方案
使用mybatis类型转换器,自定义类型转换器,在Mybatis执行SQL得到结果时,通过自定义类型转换器将CHAR或者VARCHAR2进行加解密处理
mybatis 类型转换器
java有java的数据类型,数据库有数据库的数据类型,那么我们在往数据库中插入数据的时候是如何把java类型当做数据库类型插入数据库,在从数据库读取数据的时候又是如何把数据库类型当做java类型来处理呢?这中间必然要经过一个类型转换。

mybatis提供了TypeHandler接口,抽象类BaseTypeHandler实现TypeHandler接口,String,Integer,Long等常见的数据类型转换都是基于继承BaseTypeHandler实现,BaseTypeHandler提供了基本的判空等操作。因此我们可以继承BaseTypeHandler或者实现TypeHandler接口完成自定义类型转换,一般建议继承BaseTypeHandler来编码

Mybatis 字段加解密_第1张图片

加解密类型转换
加解密使用了Base64(可以更换其他加解密方案)
Java代码如下:AESTypeHandler.java

package com.XXX.impl.hander;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

public class AESTypeHandler extends BaseTypeHandler<Object> {

	@Override
	public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
			throws SQLException {
		ps.setString(i, AES.encrypt((String)parameter));
	}

	@Override
	public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
		String columnValue = rs.getString(columnName);
		return AES.decrypt(columnValue);
	}

	@Override
	public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
		String columnValue = rs.getString(columnIndex);
		return AES.decrypt(columnValue);
	}
	
	@Override
	public String getNullableResult(CallableStatement cs, int columnIndex)
			throws SQLException {
		String columnValue = cs.getString(columnIndex);
		return AES.decrypt(columnValue);
	}

}

Java代码如下:AES.java

import java.util.Base64;
public class AES {
	public static String encrypt(String src) {
		try {
			String result = Base64.getEncoder().encodeToString(src.getBytes("UTF-8"));
			return result;	
		} catch (Exception e) {
			throw new RuntimeException("encrypt fail!", e);
		}
	}

	public static String decrypt(String src) {
		try {
			 byte[] asBytes = Base64.getDecoder().decode(src);
		     String result = new String(asBytes,"UTF-8");
		     return result;
		} catch (Exception e) {
			throw new RuntimeException("decrypt fail!", e);
		}
	}
}

application.yml文件如下:

#mybatis
mybatis-plus:
#   config-location: classpath:mybatis/mybatis-config.xml
    mapper-locations: classpath:mapper/*Mapper.xml
    #实体扫描,多个package用逗号或者分号分隔
    typeAliasesPackage: com.XXX.impl.entity
    typeEnumsPackage: com.XXX.impl.entity.enums
    //扫描项目下类型转换的包
    type-handlers-package: com.XXX.impl.hander

xxxMapper.xml文件如下:

<!-- 通用查询映射结果 -->
	<resultMap id="BaseResultMap"
		type="com.ashman.impl.entity.PuaInfoEntity">
		<result column="id" property="id" />
		<result column="wechat" property="wechat" />
		<result column="name" property="name" />
		<result column="tellphone" property="tellphone"
			typeHandler="com.XXX.impl.hander.AESTypeHandler" />
		<result column="image_url" property="imageUrl" />
		<result column="creater" property="creater" />
		<result column="createTime" property="createTime" />
		<result column="remark" property="remark" />
	</resultMap>
     <!--新增 需要增加类型转换 -->
	<insert id="addPuaInfo"
		parameterType="com.XXX.impl.entity.PuaInfoEntity">
		<selectKey keyProperty="id" resultType="string"
			order="BEFORE">
			select replace(uuid(), '-', '') as id from dual
		</selectKey>
		insert into pua_info (id, wechat, name,
		tellphone, image_url, creater,
		createTime, remark)
		values (#{id,jdbcType=BIGINT},
		#{wechat,jdbcType=VARCHAR},
		#{name,jdbcType=VARCHAR},
		#{tellphone,jdbcType=VARCHAR,typeHandler=com.ashman.impl.hander.AESTypeHandler},
		#{imageUrl,jdbcType=VARCHAR}, #{creater,jdbcType=VARCHAR},
		#{createTime,jdbcType=TIMESTAMP}, #{remark,jdbcType=VARCHAR})
	</insert>
<!--查询  类型转换在映射结果resultMap  -->
	<select id="queryModelList" resultMap="BaseResultMap"
		parameterType="com.XXX.impl.entity.PuaInfoEntity">
		select id, wechat, name,tellphone, image_url, creater,createTime,
		remark
		from pua_info
		<where>
			<if test="name != null">
				and name = #{name,jdbcType=VARCHAR}
			</if>
		</where>
	</select>

新增,数据库结果:
在这里插入图片描述

查询,显示结果:
在这里插入图片描述

你可能感兴趣的:(mybatis)