Mybatis的TypeHandler實現(xiàn)數(shù)據(jù)加解密詳解
一、背景
有些項目需要對一些信息入庫前進(jìn)行加密處理,為了數(shù)據(jù)安全或者隱私合規(guī),但與此同時也使數(shù)據(jù)處理變得麻煩,不可避免的會帶來重復(fù)冗長的代碼。如果能在持久層處理好數(shù)據(jù),避免在業(yè)務(wù)層處理,就能合理的規(guī)避這個問題。
二、方案
使用mybatis框架提供的TypeHandler來實現(xiàn)在持久層處理數(shù)據(jù)。
TypeHandler簡介
Typehandler是mybatis提供的一個接口,通過實現(xiàn)這個接口,可以實現(xiàn)jdbc類型數(shù)據(jù)和java類型數(shù)據(jù)的轉(zhuǎn)換,我們??吹降膙archar轉(zhuǎn)string、bigint轉(zhuǎn)long等都是mybatis自身實現(xiàn)此接口處理的。
我們可以自己實現(xiàn)一個Typehandler,滿足自己的需求。
三、詳細(xì)實現(xiàn)
1.實現(xiàn)接口,定義自己的Typehandler
一般實現(xiàn)BaseTypeHandler接口即可。筆者的加解密使用了hutool提供的des加密,maven坐標(biāo)如下:
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.10</version> </dependency>
代碼如下,可根據(jù)業(yè)務(wù)需求編寫方法實現(xiàn)代碼:
package com.example.cryptotypehandler.common; import cn.hutool.crypto.symmetric.SymmetricAlgorithm; import cn.hutool.crypto.symmetric.SymmetricCrypto; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.MappedJdbcTypes; import org.apache.ibatis.type.MappedTypes; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @Slf4j @MappedJdbcTypes(JdbcType.VARCHAR) @MappedTypes(String.class) public class CryptoTypeHandler extends BaseTypeHandler<String> { private final byte[] key = {-26, -70, -29, -99, 73, -82, 91, -50, 79, -77, 59, 104, 2, -36, 50, -22, -39, -15, -57, -89, 81, -99, 42, -89}; private final SymmetricCrypto des = new SymmetricCrypto(SymmetricAlgorithm.DESede, key); /* * 加工入?yún)? */ @Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { if (parameter != null) { //加密 String encryptHex = des.encryptHex(parameter); log.info("{} ---加密為---> {}", parameter, encryptHex); ps.setString(i, encryptHex); } } /* * 根據(jù)列名獲取返回結(jié)果,可在此方法中加工返回值 */ @Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { String originRes = rs.getString(columnName); if (originRes != null) { String res = des.decryptStr(originRes); log.info("{} ---解密為---> {}", originRes, res); return res; } log.info("結(jié)果為空,無需解密"); return null; } /* * 根據(jù)列下標(biāo)獲取返回結(jié)果,可在此方法中加工返回值 */ @Override public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { String originRes = rs.getString(columnIndex); if (originRes != null) { String res = des.decryptStr(originRes); log.info("{} ---解密為---> {}", originRes, res); return res; } log.info("結(jié)果為空,無需解密"); return null; } /* * 根據(jù)列下標(biāo)獲取返回結(jié)果(存儲過程),可在此方法中加工返回值 */ @Override public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { String originRes = cs.getString(columnIndex); if (originRes != null) { String res = des.decryptStr(originRes); log.info("{} ---解密為---> {}", originRes, res); return res; } log.info("結(jié)果為空,無需解密"); return null; } }
2.注冊自定義的TypeHandler
編寫好的TypeHandler需要注冊到mybatis中,在application.yml或者application.properties中加入配置:
properties文件:
mybatis.type-handlers-package=com.example.cryptotypehandler.common
yml文件
mybatis: type-handlers-package: com.example.cryptotypehandler.common
筆者包結(jié)構(gòu)如下
3.定義mapper層接口
實體對象類
package com.example.cryptotypehandler.domain; import lombok.Getter; import lombok.Setter; import lombok.ToString; @Getter @Setter @ToString public class AccountDO { private Long id; /** * 用戶名 */ private String userName; /** * 密碼 */ private String password; }
和普通的mapper沒區(qū)別:
package com.example.cryptotypehandler.mapper; import com.example.cryptotypehandler.domain.AccountDO; import org.apache.ibatis.annotations.Mapper; import java.util.List; /** * <p> * Mapper 接口 * </p> * * @author shuai.mh * @since 2022-11-29 */ @Mapper public interface AccountMapper { int insertEncrypt(AccountDO accountDO); List<AccountDO> selectAccount(AccountDO accountDO); }
4.編寫mapper.xml
這邊有幾個注意點:
- 首先看insert語句,我們需要加密的是password字段,因此在password后加上typeHandler=com.example.cryptotypehandler.common.CryptoTypeHandler;此外,#{userName}中,jdbcType=varchar不要填寫,因為自定義的typerHandler中加了下面兩個注解:@MappedJdbcTypes(JdbcType.VARCHAR)和@MappedTypes(String.class),這兩個注解表示JdbcType為varchar是會使用此handler,加了的話,userName也會被加密。
- 再看select語句,sql和普通的沒有區(qū)別,但是resultMap中的password映射加了typeHandler="com.example.cryptotypehandler.common.CryptoTypeHandler",代表此字段在轉(zhuǎn)換成實體對象時會被handler處理,此外其他字段的映射jdbcType保持缺省,如果是varchar也會被處理。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.cryptotypehandler.mapper.AccountMapper"> <!-- 通用查詢映射結(jié)果 --> <resultMap id="BaseResultMap" type="com.example.cryptotypehandler.domain.AccountDO"> <id column="id" property="id" /> <result column="user_name" property="userName"/> <result column="password" property="password" typeHandler="com.example.cryptotypehandler.common.CryptoTypeHandler" /> </resultMap> <!-- 通用查詢結(jié)果列 --> <sql id="Base_Column_List"> id, user_name, password </sql> <insert id="insertEncrypt"> insert into account (id, user_name, password) values (#{id}, #{userName}, #{password, typeHandler=com.example.cryptotypehandler.common.CryptoTypeHandler}) </insert> <select id="selectAccount" resultMap="BaseResultMap"> select <include refid="Base_Column_List"></include> from account where user_name = #{userName} </select> </mapper>
5.調(diào)用接口,簡單測試
①新增用戶
②查看數(shù)據(jù)庫,密碼已被加密
③查詢用戶,查詢結(jié)果已解密
到此這篇關(guān)于Mybatis的TypeHandler實現(xiàn)數(shù)據(jù)加解密詳解的文章就介紹到這了,更多相關(guān)TypeHandler數(shù)據(jù)加解密內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- MyBatis?typeHandler接口的定義和使用
- MyBatis中的自定義TypeHandler詳解
- Mybatis中自定義TypeHandler處理枚舉的示例代碼
- Mybatis中TypeHandler使用小結(jié)
- SpringBoot中MyBatis使用自定義TypeHandler的實現(xiàn)
- Mybatis使用typeHandler加密的實現(xiàn)
- MyBatis-Plus?中?typeHandler?的使用實例詳解
- MyBatis中TypeHandler的使用教程詳解
- MyBatis類型處理器TypeHandler的作用及說明
- MyBatis自定義TypeHandler實現(xiàn)字段加密解密
相關(guān)文章
SpringCloud客戶端報錯:- was unable to send&nb
這篇文章主要介紹了SpringCloud客戶端報錯:- was unable to send heartbeat!的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-05-05IntelliJ IDEA 統(tǒng)一設(shè)置編碼為utf-8編碼的實現(xiàn)
這篇文章主要介紹了IntelliJ IDEA 統(tǒng)一設(shè)置編碼為utf-8編碼的實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2020-06-06