mybatis類型轉(zhuǎn)換器如何實(shí)現(xiàn)數(shù)據(jù)加解密
mybatis類型轉(zhuǎn)換器數(shù)據(jù)加解密
背景需求
對(duì)表中的某些字段進(jìn)行加密,查詢之后對(duì)字段進(jìn)行解密,業(yè)務(wù)代碼無需關(guān)注加解密環(huán)節(jié)。
mybatis 攔截器 vs 類型轉(zhuǎn)換器
mybatis的攔截器能實(shí)現(xiàn)上面的需求,但是會(huì)攔截所有的sql語句,如果項(xiàng)目中只是部分sql涉及到加解密操作,還是比較犧牲大局的。實(shí)現(xiàn)起來也比較麻煩,特別是單參數(shù)查詢的時(shí)候,比如參數(shù)名稱name,此時(shí)需要對(duì)name進(jìn)行加密就相對(duì)困難。如果是多參數(shù),因?yàn)榈讓訒?huì)將參數(shù)封裝成Map,可以根據(jù)是否含有指定的key進(jìn)行加密。
mybatis類型轉(zhuǎn)換器也可以實(shí)現(xiàn)上面的需求,方案為修改xml里面的配置,指定類型轉(zhuǎn)換器,并在轉(zhuǎn)換器里面實(shí)現(xiàn)數(shù)據(jù)的加解密。
mybatis 類型轉(zhuǎn)換器
java有java的數(shù)據(jù)類型,數(shù)據(jù)庫(kù)有數(shù)據(jù)庫(kù)的數(shù)據(jù)類型,那么我們?cè)谕鶖?shù)據(jù)庫(kù)中插入數(shù)據(jù)的時(shí)候是如何把java類型當(dāng)做數(shù)據(jù)庫(kù)類型插入數(shù)據(jù)庫(kù),在從數(shù)據(jù)庫(kù)讀取數(shù)據(jù)的時(shí)候又是如何把數(shù)據(jù)庫(kù)類型當(dāng)做java類型來處理呢?這中間必然要經(jīng)過一個(gè)類型轉(zhuǎn)換。
mybatis提供了TypeHandler接口,抽象類BaseTypeHandler實(shí)現(xiàn)TypeHandler接口,String,Integer,Long等常見的數(shù)據(jù)類型轉(zhuǎn)換都是基于繼承BaseTypeHandler實(shí)現(xiàn),BaseTypeHandler提供了基本的判空等操作。因此我們可以繼承BaseTypeHandler或者實(shí)現(xiàn)TypeHandler接口完成自定義類型轉(zhuǎn)換,一般建議繼承BaseTypeHandler來編碼。

數(shù)據(jù)加解密類型轉(zhuǎn)換
假設(shè)加解密采用AES算法,此處對(duì)加解密結(jié)果做一下緩存,因?yàn)橐恍?shù)據(jù)是一樣的,如果每次都去加密,也是會(huì)消耗一定的時(shí)間
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)));
}
}
使用方法
針對(duì)sql語句,在xml配置文件中,對(duì)需要加密的字段加上
#{name,jdbcType=VARCHAR,typeHandler=com..........DataSecurityHandler},
針對(duì)查詢結(jié)果,在xml配置文件中,在resultMap里面對(duì)需要解密的字段加上
<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;
}
}
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- MybatisPlus字段類型轉(zhuǎn)換的實(shí)現(xiàn)示例
- mybatis自定義參數(shù)類型轉(zhuǎn)換器數(shù)據(jù)庫(kù)字段加密脫敏
- mybatis-plus?分頁(yè)類型轉(zhuǎn)換工具類
- 使用?mybatis?自定義日期類型轉(zhuǎn)換器的示例代碼
- Mybatis自定義類型轉(zhuǎn)換器的使用技巧
- MyBatis自定義類型轉(zhuǎn)換器實(shí)現(xiàn)加解密
- Mybatis實(shí)現(xiàn)自定義類型轉(zhuǎn)換器TypeHandler的方法
- MyBatis類型轉(zhuǎn)換模塊的實(shí)現(xiàn)
相關(guān)文章
Java Spring @Autowired的這些騷操作,你都知道嗎
這篇文章主要介紹了徹底搞明白Spring中的自動(dòng)裝配和Autowired注解的使用,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2021-09-09
MyBatisPlus?大數(shù)據(jù)量查詢慢的問題解決
本文主要介紹了MyBatis?Plus?解決大數(shù)據(jù)量查詢慢問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02
SpringBoot 整合 Netty 多端口監(jiān)聽的操作方法
Netty提供異步的、基于事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用程序框架,用以快速開發(fā)高性能、高可靠性的網(wǎng)絡(luò) IO 程序,是目前最流行的 NIO 框架,這篇文章主要介紹了SpringBoot 整和 Netty 并監(jiān)聽多端口,需要的朋友可以參考下2023-10-10
解決maven常見錯(cuò)誤:Dependency is duplicated in
這篇文章主要介紹了解決maven常見錯(cuò)誤:Dependency is duplicated in file(s):問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04

