利用mybatis拦截器对数据库敏感字段加解密
前言
由于公司业务要求,需要在不影响已有业务上对 数据库中已有数据的敏感字段加密解密,个人解决方案利用mybatis的拦截器加密解密敏感字段
思路解析
- 利用注解标明需要加密解密的entity类对象以及其中的数据
- mybatis拦截Executor.class对象中的query,update方法
- 在方法执行前对parameter进行加密解密,在拦截器执行后,解密返回的结果
代码
1、配置拦截器(interceptor后为自己拦截器的包路径)
<plugins>
<plugin interceptor="com.github.miemiedev.mybatis.paginator.OffsetLimitInterceptor">
<property name="dialectClass" value="com.github.miemiedev.mybatis.paginator.dialect.OracleDialect" />
</plugin>
<plugin interceptor="com.XXX.XXXX.service.encryptinfo.DaoInterceptor" />
</plugins>
2、拦截器的实现
特别注意:因为Dao方法参数有可能单一参数,多参数map形式,以及entity对象参数类型,所以不通类型需有不通的处理方式(本文参数 单一字符串和entity对象,返回的结果集 List<?> 和entity)
后续在拦截器中添加了相应的开关,控制参数是否加密查询,解密已实现兼容
package com.ips.fpms.service.encryptinfo;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import com.xxx.xxx.dao.WhiteListDao;
import com.xxx.xxx.entity.db.WhiteListEntity;
import com.xxx.xxx.service.util.SpringBeanUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.xxx.xxx.annotation.EncryptField;
import com.xxx.xxx.annotation.EncryptMethod;
import com.xxx.xxx.common.utils.CloneUtil;
import com.xxx.core.psfp.common.support.JsonUtils;
import com.xxx.xxx.service.util.CryptPojoUtils;
@Intercepts({
@Signature(type=Executor.class,method="update",args={
MappedStatement.class,Object.class}),
@Signature(type=Executor.class,method="query",args={
MappedStatement.class,Object.class,RowBounds.class,ResultHandler.class})
})
public class EncryptDaoInterceptor implements Interceptor{
private final Logger logger = LoggerFactory.getLogger(EncryptDaoInterceptor.class);
private WhiteListDao whiteListDao;
static int MAPPED_STATEMENT_INDEX = 0;
static int PARAMETER_INDEX = 1;
static int ROWBOUNDS_INDEX = 2;
static int RESULT_HANDLER_INDEX = 3;
static String ENCRYPTFIELD = "1";
static String DECRYPTFIELD = "2";
private static final String ENCRYPT_KEY = "encry146local";
private static final String ENCRYPT_NUM = "146";
private static boolean ENCRYPT_SWTICH = true;
/**
* 是否进行加密查询
* @return 1 true 代表加密 0 false 不加密
*/
private boolean getFuncSwitch(){
if(whiteListDao == null){
whiteListDao = SpringBeanUtils.getBean("whiteListDao",WhiteListDao.class);
}
try{
WhiteListEntity entity = whiteListDao.selectOne(ENCRYPT_KEY,ENCRYPT_NUM);
if(entity!=null<