最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Mybatis基于TypeHandler實(shí)現(xiàn)敏感數(shù)據(jù)加密

 更新時(shí)間:2023年10月15日 15:24:38   作者:小星星*  
業(yè)務(wù)場(chǎng)景中經(jīng)常會(huì)遇到諸如用戶手機(jī)號(hào),身份證號(hào),銀行卡號(hào),郵箱,地址,密碼等等信息,屬于敏感信息,本文就來介紹一下Mybatis基于TypeHandler實(shí)現(xiàn)敏感數(shù)據(jù)加密,感興趣的可以了解一下

一、介紹

業(yè)務(wù)場(chǎng)景中經(jīng)常會(huì)遇到諸如用戶手機(jī)號(hào),身份證號(hào),銀行卡號(hào),郵箱,地址,密碼等等信息,屬于敏感信息,需要保存在數(shù)據(jù)庫中。而很多公司會(huì)會(huì)要求對(duì)數(shù)據(jù)庫中的此類數(shù)據(jù)進(jìn)行加密存儲(chǔ)。

敏感數(shù)據(jù)脫敏需要處理的兩個(gè)問題:

  • 查詢操作,需要對(duì)查詢的關(guān)鍵字進(jìn)行加密,同時(shí)也要對(duì)從庫中查到的數(shù)據(jù)進(jìn)行解密
  • 插入和更新操作,需要對(duì)插入或者更新的數(shù)據(jù)進(jìn)行加密,然后保存到數(shù)據(jù)庫

二、解決思路

使用mybatis框架提供的TypeHandler來實(shí)現(xiàn)在持久層處理數(shù)據(jù)。

Typehandlermybatis提供的一個(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é)果為空,無需解密");
        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é)果(存儲(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é)果為空,無需解密");
        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)文章

  • Spring-boot 中@Async使用遇到的坑

    Spring-boot 中@Async使用遇到的坑

    這篇文章主要介紹了Spring-boot 中@Async使用的坑,首先使用@Async 需要在Spring啟動(dòng)類上添加注解@EnableAsyn或者在你們線程池配置類添加@EnableAsyn,需要的朋友可以參考下
    2024-01-01
  • Java多線程實(shí)現(xiàn)Runnable方式

    Java多線程實(shí)現(xiàn)Runnable方式

    這篇文章主要為大家詳細(xì)介紹了Java多線程如何實(shí)現(xiàn)Runnable方式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • java簡(jiǎn)單實(shí)現(xiàn)自定義日歷

    java簡(jiǎn)單實(shí)現(xiàn)自定義日歷

    這篇文章主要為大家詳細(xì)介紹了java簡(jiǎn)單實(shí)現(xiàn)自定義日歷,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Gradle構(gòu)建Java項(xiàng)目指定JDK版本與編譯參數(shù)實(shí)戰(zhàn)演練

    Gradle構(gòu)建Java項(xiàng)目指定JDK版本與編譯參數(shù)實(shí)戰(zhàn)演練

    Gradle是一種流行的構(gòu)建工具,廣泛用于Java、Android和其他項(xiàng)目,通過配置環(huán)境變量,您可以更好地控制Gradle構(gòu)建過程,這篇文章主要介紹了Gradle構(gòu)建Java項(xiàng)目指定JDK版本與編譯參數(shù)的相關(guān)資料,需要的朋友可以參考下
    2026-04-04
  • SpringBoot 數(shù)據(jù)存儲(chǔ)實(shí)戰(zhàn)指南

    SpringBoot 數(shù)據(jù)存儲(chǔ)實(shí)戰(zhàn)指南

    Elasticsearch是一個(gè)基于Apache Lucene開發(fā)的的搜索服務(wù),提供了一個(gè)分布式多用戶能力的全文搜索引擎,本文介紹如何在SpringBoot項(xiàng)目中整合ElasticSearch來完成數(shù)據(jù)的存儲(chǔ),感興趣的朋友跟隨小編一起看看吧
    2026-03-03
  • SpringBoot中的數(shù)據(jù)脫敏處理詳解

    SpringBoot中的數(shù)據(jù)脫敏處理詳解

    本文介紹了在SpringBoot中進(jìn)行數(shù)據(jù)脫敏處理的方法,通過自定義注解和Jackson配置,可以輕松實(shí)現(xiàn)對(duì)敏感數(shù)據(jù)的脫敏,保護(hù)用戶隱私
    2025-03-03
  • SpringBoot整合knife4j3.0.3實(shí)現(xiàn)過程

    SpringBoot整合knife4j3.0.3實(shí)現(xiàn)過程

    文章介紹了如何在SpringBoot項(xiàng)目中使用Swagger和Knife4j來生成和增強(qiáng)API文檔,Swagger通過注解自動(dòng)生成API文檔,而Knife4j則提供了更豐富的功能,如在線調(diào)試、多語言支持和離線文檔導(dǎo)出等,通過配置和使用這些工具,可以提高API文檔的管理和使用效率
    2026-01-01
  • Java樂觀鎖防止數(shù)據(jù)沖突的詳細(xì)過程

    Java樂觀鎖防止數(shù)據(jù)沖突的詳細(xì)過程

    樂觀鎖是一種并發(fā)控制機(jī)制,用于防止多個(gè)事務(wù)同時(shí)修改同一數(shù)據(jù)導(dǎo)致的數(shù)據(jù)不一致問題,它通過在數(shù)據(jù)記錄中添加一個(gè)版本號(hào)或時(shí)間戳字段,來判斷數(shù)據(jù)在兩次操作之間是否被其他事務(wù)修改本文介紹了樂觀鎖防止數(shù)據(jù)沖突的詳細(xì)過程
    2025-04-04
  • JavaCV實(shí)現(xiàn)讀取視頻信息及自動(dòng)截取封面圖詳解

    JavaCV實(shí)現(xiàn)讀取視頻信息及自動(dòng)截取封面圖詳解

    javacv可以幫助我們?cè)趈ava中很方便的使用OpenCV以及FFmpeg相關(guān)的功能接口。本文將利用Javacv實(shí)現(xiàn)在視頻網(wǎng)站中常見的讀取視頻信息和自動(dòng)獲取封面圖的功能,感興趣的可以了解一下
    2022-06-06
  • maven解決包沖突方法詳解

    maven解決包沖突方法詳解

    這篇文章主要介紹了maven解決包沖突方法詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10

最新評(píng)論

大洼县| 普宁市| 玛沁县| 玛纳斯县| 手游| 刚察县| 河东区| 盘山县| 左贡县| 福贡县| 黄浦区| 富顺县| 会泽县| 绍兴县| 通榆县| 蒙阴县| 玉林市| 雷山县| 海晏县| 黔江区| 临城县| 永清县| 高尔夫| 宜宾县| 湘潭市| 丘北县| 昭平县| 榆社县| 龙山县| 兴城市| 鹤岗市| 鄂州市| 夹江县| 高台县| 万山特区| 镇巴县| 南陵县| 巨鹿县| 岫岩| 连南| 云梦县|