mybatis类型转换器如何实现数据加解密

 更新时间:2021年09月23日 10:05:21   作者:userwyh  
这篇文章主要介绍了mybatis类型转换器如何实现数据加解密,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

mybatis类型转换器数据加解密

背景需求

对表中的某些字段进行加密,查询之后对字段进行解密,业务代码无需关注加解密环节。

mybatis 拦截器 vs 类型转换器

mybatis的拦截器能实现上面的需求,但是会拦截所有的sql语句,如果项目中只是部分sql涉及到加解密操作,还是比较牺牲大局的。实现起来也比较麻烦,特别是单参数查询的时候,比如参数名称name,此时需要对name进行加密就相对困难。如果是多参数,因为底层会将参数封装成Map,可以根据是否含有指定的key进行加密。

mybatis类型转换器也可以实现上面的需求,方案为修改xml里面的配置,指定类型转换器,并在转换器里面实现数据的加解密。

mybatis 类型转换器

java有java的数据类型,数据库有数据库的数据类型,那么我们在往数据库中插入数据的时候是如何把java类型当做数据库类型插入数据库,在从数据库读取数据的时候又是如何把数据库类型当做java类型来处理呢?这中间必然要经过一个类型转换。

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

数据加解密类型转换

假设加解密采用AES算法,此处对加解密结果做一下缓存,因为一些数据是一样的,如果每次都去加密,也是会消耗一定的时间

public class DataSecurityHandler extends BaseTypeHandler {
    public static final LoadingCache<String, String> ENCRYPT_CACHE = CacheBuilder.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).build(new CacheLoader<String, String>() {
        public String load(String parameterValue) {
            return AES.encrypt(parameterValue);
        }
    });
    public static final LoadingCache<String, String> DECRYPT_CACHE = CacheBuilder.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).build(new CacheLoader<String, String>() {
        public String load(String parameterValue) {
            return AES.decrypt(parameterValue);
        }
    });
    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        String parameterValue = (String) parameter;
        String resultValue = ENCRYPT_CACHE.getUnchecked(StringUtils.trimToEmpty(parameterValue));
        preparedStatement.setString(i, resultValue);
    }
    @Override
    public Object getNullableResult(ResultSet resultSet, String s) throws SQLException {
        return DECRYPT_CACHE.getUnchecked(StringUtils.trimToEmpty(resultSet.getString(s)));
    }
    @Override
    public Object getNullableResult(ResultSet resultSet, int i) throws SQLException {
        return DECRYPT_CACHE.getUnchecked(StringUtils.trimToEmpty(resultSet.getString(i)));
    }
    @Override
    public Object getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        return DECRYPT_CACHE.getUnchecked(StringUtils.trimToEmpty(callableStatement.getString(i)));
    }
}

使用方法

针对sql语句,在xml配置文件中,对需要加密的字段加上

#{name,jdbcType=VARCHAR,typeHandler=com..........DataSecurityHandler},

针对查询结果,在xml配置文件中,在resultMap里面对需要解密的字段加上

<result column="name" property="name" jdbcType="VARCHAR" typeHandler="com.*..........DataSecurityHandler"/>

mybatis密码解密

mybatis的配置

properties的配置

代码:

 
package com.finance.entity.batctrl; 
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Properties; 
import javax.sql.DataSource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
 
import org.apache.commons.codec.binary.Base64;
import org.apache.ibatis.datasource.pooled.PooledDataSource;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;  
public class MyBatisSessionFactory { 
 
	/**
	 * session工厂
	 */
	private final static SqlSessionFactory sqlSessionFactory;
 
	/**
	 * 日志类
	 */
	private static Logger logger = LoggerFactory.getLogger(MyBatisSessionFactory.class);
 
	static {
        String resource = "mybatis-configuration.xml"; 
        //Reader reader = null;
        InputStream inputStream = null; 
        Properties props = new Properties();
        try {
            //reader = Resources.getResourceAsReader(resource);        	        	            
            InputStream in = Resources.getResourceAsStream("batch.properties");
            
            props.load(in);
            String url= props.getProperty("jdbc.url");
            String username= props.getProperty("jdbc.username");
            String password= props.getProperty("jdbc.password");
            
            logger.debug("befor url -> "+url);
            logger.debug("befor username -> "+username);
            logger.debug("befor decode -> "+password);
            
            byte[] b = Base64.decodeBase64(password.getBytes());
            String decode = new String(b);
            props.put("url",url);
            props.put("username",username);
            props.put("password",decode);
            logger.debug("after url -> "+url);
            logger.debug("after username -> "+username);
            logger.debug("after decode -> "+decode);
            inputStream = Resources.getResourceAsStream(resource);        
        } catch (IOException e) {
        }        
        
        //sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream ,props );
    }
 
	public static SqlSessionFactory getSessionFactory() {
		return sqlSessionFactory;
	} 
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java Spring @Autowired的这些骚操作,你都知道吗

    Java Spring @Autowired的这些骚操作,你都知道吗

    这篇文章主要介绍了彻底搞明白Spring中的自动装配和Autowired注解的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2021-09-09
  • 一文彻底搞懂Java和JDK的版本命名问题

    一文彻底搞懂Java和JDK的版本命名问题

    今天通过本文给大家分享我对Java的版本号以及JDK的命名的了解,通过实例图文展示给大家介绍的非常详细,需要的朋友跟随小编一起看看吧
    2021-06-06
  • MyBatisPlus 大数据量查询慢的问题解决

    MyBatisPlus 大数据量查询慢的问题解决

    本文主要介绍了MyBatis Plus 解决大数据量查询慢问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • Mybatis-plus sql注入及防止sql注入详解

    Mybatis-plus sql注入及防止sql注入详解

    mybatis-plus提供了许多默认单表 CRUD 语句,对于其他SQL情况爱莫能助,下面这篇文章主要给大家介绍了关于Mybatis-plus sql注入及防止sql注入的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-10-10
  • SpringBoot 整合 Netty 多端口监听的操作方法

    SpringBoot 整合 Netty 多端口监听的操作方法

    Netty提供异步的、基于事件驱动的网络应用程序框架,用以快速开发高性能、高可靠性的网络 IO 程序,是目前最流行的 NIO 框架,这篇文章主要介绍了SpringBoot 整和 Netty 并监听多端口,需要的朋友可以参考下
    2023-10-10
  • JAVA项目字典与缓存搭配使用方法解析

    JAVA项目字典与缓存搭配使用方法解析

    这篇文章主要介绍了JAVA项目字典与缓存搭配使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • Java的sort的排序及使用详解

    Java的sort的排序及使用详解

    这篇文章主要为大家详细介绍了Java的sort的排序及使用,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 ,希望您能够多多关注
    2022-02-02
  • jdbc与druid连接池的使用详解

    jdbc与druid连接池的使用详解

    这篇文章主要介绍了jdbc与druid连接池的使用详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • 解决maven常见错误:Dependency is duplicated in file(s):

    解决maven常见错误:Dependency is duplicated in 

    这篇文章主要介绍了解决maven常见错误:Dependency is duplicated in file(s):问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • Java装饰者模式的示例详解

    Java装饰者模式的示例详解

    装饰者模式:在不改变原有对象的基础之上,动态的将功能附加到对象上,提供了继承更有弹性的替代方案,也体现了开闭原则。本文将通过示例详细讲解一下装饰者模式,需要的可以参考一下
    2022-02-02

最新评论