Mybatis基于TypeHandler實(shí)現(xiàn)敏感數(shù)據(jù)加密
一、介紹
業(yè)務(wù)場(chǎng)景中經(jīng)常會(huì)遇到諸如用戶手機(jī)號(hào),身份證號(hào),銀行卡號(hào),郵箱,地址,密碼等等信息,屬于敏感信息,需要保存在數(shù)據(jù)庫(kù)中。而很多公司會(huì)會(huì)要求對(duì)數(shù)據(jù)庫(kù)中的此類數(shù)據(jù)進(jìn)行加密存儲(chǔ)。
敏感數(shù)據(jù)脫敏需要處理的兩個(gè)問題:
- 查詢操作,需要對(duì)查詢的關(guān)鍵字進(jìn)行加密,同時(shí)也要對(duì)從庫(kù)中查到的數(shù)據(jù)進(jìn)行解密
- 插入和更新操作,需要對(duì)插入或者更新的數(shù)據(jù)進(jìn)行加密,然后保存到數(shù)據(jù)庫(kù)
二、解決思路
使用mybatis
框架提供的TypeHandler
來實(shí)現(xiàn)在持久層處理數(shù)據(jù)。
Typehandler
是mybatis
提供的一個(gè)接口,通過實(shí)現(xiàn)這個(gè)接口,可以實(shí)現(xiàn)jdbc類型數(shù)據(jù)和java類型數(shù)據(jù)的轉(zhuǎn)換,我們??吹降膙archar轉(zhuǎn)string、bigint轉(zhuǎn)long等都是mybatis自身實(shí)現(xiàn)此接口處理的。
因此,可以自己實(shí)現(xiàn)一個(gè)Typehandler
,滿足自己的數(shù)據(jù)處理需求。
優(yōu)點(diǎn):實(shí)現(xiàn)也簡(jiǎn)單,使用方便,整個(gè)使用過程只需要對(duì)xml代碼做修改
三、實(shí)現(xiàn)
1. 加解密方法: 這里的加解密方法就直接使用hutool的des加密了。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- hutool-all 含接加密工具 --> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.15</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- mybatis --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency>
2. 編寫自定義的TypeHandler,繼承自BaseTypeHandler
package com.zsx.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; /** * @Description typeHandler加解密處理器 將String類型的字段加密或解密 * @author zhousx * @Data 2023-10-15 13:02 */ @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é)果為空,無(wú)需解密"); 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é)果為空,無(wú)需解密"); return null; } /* * 根據(jù)列下標(biāo)獲取返回結(jié)果(存儲(chǔ)過程),可在此方法中加工返回值 */ @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é)果為空,無(wú)需解密"); return null; } }
3. 注冊(cè)自定義的typeHandler到mybatis
application.yml
server: port: 8082 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&characterEncoding=utf8&useSSL=true username: root password: 123456 mybatis: # 編寫好的TypeHandler需要注冊(cè)到mybatis中 type-handlers-package: com.zsx.cryptotypehandler.common mapper-locations: classpath:mapper/*.xml configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
4. 使用
實(shí)體類 User.java
package com.zsx.entity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String name; private String phone; }
dao層 IUserDao.java
package com.zsx.dao; import com.zsx.entity.User; import org.apache.ibatis.annotations.Mapper; import java.util.List; /** * userMapper */ @Mapper public interface IUserDao { int insertEncrypt(User user); List<User> findByName(User user); List<User> findByPhone(User user); List<User> findByPhone2(String phone); }
xml文件 UserMapper.xml
<?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.zsx.dao.IUserDao"> <!-- 通用查詢映射結(jié)果 --> <resultMap id="BaseResultMap" type="com.zsx.entity.User"> <id column="id" property="id" /> <result column="name" property="name"/> <!-- 結(jié)果集里需要解密的字段,加上typeHandler --> <result column="phone" property="phone" typeHandler="com.zsx.common.CryptoTypeHandler" /> </resultMap> <!-- sql傳參里需要加密的字段,加上typeHandler --> <insert id="insertEncrypt"> insert into user (id, name, phone) values (#{id}, #{name}, #{phone,typeHandler=com.zsx.common.CryptoTypeHandler}) </insert> <select id="findByName" resultMap="BaseResultMap"> select id, name, phone from user where name = #{name} </select> <!-- sql傳參里需要加密的字段,加上typeHandler --> <select id="findByPhone" resultMap="BaseResultMap"> select id, name, phone from user where phone = #{phone,typeHandler=com.zsx.common.CryptoTypeHandler} </select> <!-- sql傳參里需要加密的字段,加上typeHandler --> <select id="findByPhone2" resultMap="BaseResultMap"> select id, name, phone from user where phone = #{phone,typeHandler=com.zsx.common.CryptoTypeHandler} </select> </mapper>
最后的測(cè)試代碼 EncryptTypeHandlerTest.java
package com.zsx; import com.zsx.dao.IUserDao; import com.zsx.entity.User; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.util.List; @SpringBootTest public class EncryptTypeHandlerTest { @Autowired private IUserDao userDao; @Test public void testInsert(){ User user = new User(); user.setPhone("11112222333"); user.setName("zsx"); int result = userDao.insertEncrypt(user); System.out.println(result); } @Test public void testSelectByName(){ User user = new User(); user.setName("zsx"); List<User> userList = userDao.findByName(user); System.out.println(userList.toString()); } @Test public void testSelectByPhone(){ User user = new User(); user.setPhone("11112222333"); List<User> userList = userDao.findByPhone(user); System.out.println(userList.toString()); } @Test public void testSelectByPhone2(){ List<User> userList = userDao.findByPhone2("11112222333"); System.out.println(userList.toString()); } }
項(xiàng)目結(jié)構(gòu)如下
需要注意:
sql查詢的結(jié)果,必須要使用 resultMap 映射,否則就不能完成結(jié)果字段的自動(dòng)解密
到此這篇關(guān)于Mybatis基于TypeHandler實(shí)現(xiàn)敏感數(shù)據(jù)加密的文章就介紹到這了,更多相關(guān)Mybatis TypeHandler敏感數(shù)據(jù)加密內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java中的equals()和toString()方法實(shí)例詳解
這篇文章主要介紹了java中的equals()和toString()方法實(shí)例詳解的相關(guān)資料,這里舉例說明,并附實(shí)例代碼,和實(shí)現(xiàn)效果圖,需要的朋友可以參考下2016-11-11SpringBoot前后端傳輸加密設(shè)計(jì)實(shí)現(xiàn)方案
這篇文章主要給大家介紹了關(guān)于SpringBoot前后端傳輸加密設(shè)計(jì)實(shí)現(xiàn)方案的相關(guān)資料,包括數(shù)據(jù)加密方案、解密傳輸數(shù)據(jù)實(shí)現(xiàn)方案和響應(yīng)數(shù)據(jù)加密實(shí)現(xiàn)方案,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-11-11SpringBoot返回多種格式的數(shù)據(jù)的實(shí)現(xiàn)示例
本文主要介紹了SpringBoot返回多種格式的數(shù)據(jù)的實(shí)現(xiàn)示例,主要包括了FastJson,xml,pdf,excel,資源流,具有一定的參考價(jià)值,感興趣的可以了解一下2021-10-10