Mybatis的TypeHandler加解密数据实现

一、背景

在我们数据库中有些时候会保存一些用户的敏感信息,比如: 手机号、银行卡等信息,如果这些信息以明文的方式保存,那么是不安全的。假如: 黑客黑进了数据库,或者离职人员导出了数据,那么就可能导致这些敏感数据的泄漏。因此我们就需要找到一种方法来解决这个问题。

二、解决方案

由于我们系统中使用了Mybatis作为数据库持久层,因此决定使用Mybatis的TypeHandler或Plugin来解决。

TypeHandler : 需要我们在某些列上手动指定 typeHandler 来选择使用那个typeHandler或者根据@MappedJdbcTypes 和 @MappedTypes注解来自行推断。

<result column="phone" property="phone" typeHandler="com.huan.study.mybatis.typehandler.EncryptTypeHandler"/>

Plugin : 可以拦截系统中的 select、insert、update、delete等语句,也能获取到sql执行前的参数和执行后的数据。

经过考虑,决定使用TypeHandler来加解密数据。

三、需求

我们有一张客户表customer,里面有客户手机号(phone)和客户地址(address)等字段,其中客户手机号(phone)是需要加密保存到数据库中的。

1、在添加客户信息时,自动将客户手机号加密保存到数据中。

2、在查询客户信息时,自动解密客户手机号。

四、实现思路

1、编写一个实体类,凡是此实体类的数据都表示需要加解密的

public class Encrypt {
    private String value;

    public Encrypt() {
    }

    public Encrypt(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

2、编写一个加解密的TypeHandler

  • 设置参数时,加密数据。
  • 从数据库获取记录时,解密数据。
package com.huan.study.mybatis.typehandler;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
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.nio.charset.StandardCharsets;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 加解密TypeHandler
 *
 * @author huan.fu 2021/5/18 - 上午9:20
 */
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(Encrypt.class)
public class EncryptTypeHandler extends BaseTypeHandler<Encrypt> {

    private static final byte[] KEYS = "12345678abcdefgh".getBytes(StandardCharsets.UTF_8);

    /**
     * 设置参数
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Encrypt parameter, JdbcType jdbcType) throws SQLException {
        if (parameter == null || parameter.getValue() == null) {
            ps.setString(i, null);
            return;
        }
        AES aes = SecureUtil.aes(KEYS);
        String encrypt = aes.encryptHex(parameter.getValue());
        ps.setString(i, encrypt);
    }

    /**
     * 获取值
     */
    @Override
    public Encrypt getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return decrypt(rs.getString(columnName));
    }

    /**
     * 获取值
     */
    @Override
    public Encrypt getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return decrypt(rs.getString(columnIndex));
    }

    /**
     * 获取值
     */
    @Override
    public Encrypt getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return decrypt(cs.getString(columnIndex));
    }

    public Encrypt decrypt(String value) {
        if (null == value) {
            return null;
        }
        return new Encrypt(SecureUtil.aes(KEYS).decryptStr(value));
    }
}

注意⚠️:

  • @MappedTypes:表示该处理器处理的java类型是什么。
  • @MappedJdbcTypes:表示处理器处理的Jdbc类型。

3、sql语句中写法

<?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.huan.study.mybatis.mappers.CustomerMapper">

    <resultMap id="BaseResultMapper" type="com.huan.study.mybatis.entity.Customer">
        <id column="id" property="id"/>
        <result column="phone" property="phone"/>
        <result column="address" property="address"/>
    </resultMap>

    <insert id="addCustomer">
        insert into customer(phone,address) values (#{phone},#{address})
    </insert>

    <select id="findCustomer" resultMap="BaseResultMapper">
        select * from customer where phone = #{phone}
    </select>

</mapper>

SQL中没有什么特殊的写法。

4、配置文件中指定Typehandler的包路径

mybatis.type-handlers-package=com.huan.study.mybatis.typehandler

5、编写后台代码

  • 提供一个添加方法
  • 提供一个根据手机号查询的方法

后台代码比较简单,直接查看 https://gitee.com/huan1993/spring-cloud-parent/tree/master/mybatis/mybatis-typehandler-encrypt

贴一个mapper层的截图。

mapper层的写法

6、测试结果

数据库字段加解密结果

从测试结果中可知,添加数据时,需要加密的数据(phone)在数据库中已经加密了,在查询的时候,加密的数据已经自动解密了。

五、实现代码

后台代码: https://gitee.com/huan1993/spring-cloud-parent/tree/master/mybatis/mybatis-typehandler-encrypt

六、参考文档

1、https://mybatis.org/mybatis-3/zh/configuration.html#typeHandlers

2、https://github.com/mybatis/spring-boot-starter

到此这篇关于Mybatis的TypeHandler加解密数据实现的文章就介绍到这了,更多相关Mybatis TypeHandler加解密内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Mybatis实现自定义类型转换器TypeHandler的方法

    先给大家简单介绍下mybatis MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录. 此文其实是java操作Oracle类型XMLType总结二:使用Mybatis附带的一篇小结. Mybatis实现自定义的转换器,

  • Mybatis实现自定义的typehandler三步曲

    第一步实现接口TypeHandler<T> @MappedJdbcTypes(JdbcType.TIMESTAMP)//此处如果不使用该注解,在myabtis-config.xml中注册该typehandler的时候需要写明jdbctype="TIMESTAMP" @MappedTypes(DateTime.class)//此处如果不使用该注解,在myabtis-config.xml中注册该typehandler的时候需要写明javatype="com.sinos

  • Mybatis实战之TypeHandler高级进阶

    上篇文章分享了在项目实战中自定义Mybatis的TypeHandler来处理枚举类型.文章结尾也指出了美中不足之处,那就是每次都需要指定我们自定义的枚举TypeHandler. 随着项目枚举类型的增多,每次都要写一遍这个会令人很反感.那么,本次我们就来解决这一痛点. 思路分析 上篇文章讲到, mybatis有默认的处理枚举类型的TypeHandler,因此,我们要将我们自定义的枚举TypeHandler注册进入Mybatis. 注册完我们自定义的TypeHandler后,还得告诉Mybatis只

  • MyBatis自定义typeHandler的完整实例

    自定义typeHandler 对于自定义typeHandler来说,需要在配置文件中注册typeHandlers 然后需要实现TypeHandler接口, 一个例子 首先编写调度的处理类 package com.ming.MyBatis; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.TypeHandler; import org.apache.logging.log4j.LogManager; imp

  • Mybatis的TypeHandler加解密数据实现

    一.背景 在我们数据库中有些时候会保存一些用户的敏感信息,比如: 手机号.银行卡等信息,如果这些信息以明文的方式保存,那么是不安全的.假如: 黑客黑进了数据库,或者离职人员导出了数据,那么就可能导致这些敏感数据的泄漏.因此我们就需要找到一种方法来解决这个问题. 二.解决方案 由于我们系统中使用了Mybatis作为数据库持久层,因此决定使用Mybatis的TypeHandler或Plugin来解决. TypeHandler : 需要我们在某些列上手动指定 typeHandler 来选择使用那个ty

  • 详解Mybatis拦截器安全加解密MySQL数据实战

    需求背景 公司为了通过一些金融安全指标(政策问题)和防止数据泄漏,需要对用户敏感数据进行加密,所以在公司项目中所有存储了用户信息的数据库都需要进行数据加密改造.包括Mysql.redis.mongodb.es.HBase等. 因为在项目中是使用springboot+mybatis方式连接数据库进行增删改查,并且项目是中途改造数据.所以为了不影响正常业务,打算这次改动尽量不侵入到业务代码,加上mybatis开放的各种拦截器接口,所以就以此进行改造数据. 本篇文章讲述如何在现有项目中尽量不侵入业务方

  • T-SQL问题解决集锦 数据加解密全集

    以下代码已经在SQLServer2008上的示例数据库测试通过 问题一:如何为数据进行加密与解密,避免使用者窃取机密数据? 对于一些敏感数据,如密码.卡号,一般不能使用正常数值来存储.否则会有安全隐患.以往的加密解密都有前端应用程序来辅助完成.而数据库一般只能加密不能解密. 从2005开始提供了数据库层面的数据加密与解密.其实现方式主要有以下: 1. 利用CONVERT改变编码方式: 利用该函数把文字或数据转换成VARBINARY.但该方式不具备保护数据的能力,仅避免浏览数据的过程中能直接看到敏

  • postman数据加解密实现APP登入接口模拟请求

    目录 主要使用到的Postman功能 数据加解密 各种参数设置 真正发送的数据: 请求处理脚本[Pro-request Script] 响应处理脚本[Tests] 结果的样子 主要使用到的Postman功能 环境变量:只要新建就好了,操作都是在代码中处理的. 日志查看:菜单位置:View → show postman console ,显示这个窗口视图就可以了 请求时执行的脚本:Pre-request Script 标签页,使用语言javascript, 通常作为加密. 接受返回时执行的脚本:T

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

    目录 mybatis类型转换器数据加解密 背景需求 mybatis 类型转换器 数据加解密类型转换 使用方法 mybatis密码解密 mybatis的配置 properties的配置 mybatis类型转换器数据加解密 背景需求 对表中的某些字段进行加密,查询之后对字段进行解密,业务代码无需关注加解密环节. mybatis 拦截器 vs 类型转换器 mybatis的拦截器能实现上面的需求,但是会拦截所有的sql语句,如果项目中只是部分sql涉及到加解密操作,还是比较牺牲大局的.实现起来也比较麻烦

  • MyBatis自定义类型转换器实现加解密

    需求场景:当数据库中保存的部分数据需要加密,页面需要正常显示时.这是就需要我们自定义类型转换器,在Mybatis执行SQL得到结果时,通过自定义类型转换器将CHAR或者VARCHAR2进行加解密处理,Java代码如下: /**自定义typeHandler<br/> * 1 插入数据库, 加密 * 2 查询,解密 * @author Administrator * */ public class CryptTypeHandler implements TypeHandler<CryptTy

  • 如何通过一个注解实现MyBatis字段加解密

    目录 简介 模块 使用方法 配置项说明 开源链接 总结 简介 mybatis-crypto 是一个基于 mybatis 插件机制实现的字段加解密组件,通过一个注解即可对敏感数据进行加解密处理. 支持自定义 Encryptor.特殊字段单独指定 Encryptor 和 key ,满足大部分使用场景. 模块 mybatis-crypto 包括三个模块: mybatis-crypto-core 插件的核心功能模块 mybatis-crypto-spring-boot-starter 提供了 Sprin

  • Java OpenSSL生成的RSA公私钥进行数据加解密详细介绍

    Java中使用OpenSSL生成的RSA公私钥进行数据加解密 RSA是什么:RSA公钥加密算法是1977年由Ron Rivest.Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的.RSA取名来自开发他们三者的名字.RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加密标准.目前该加密方式广泛用于网上银行.数字签名等场合.RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困

  • Android Rsa数据加解密的介绍与使用示例

    Rsa加密 RSA是目前最有影响力的公钥加密算法,RSA也是第一个既能用于数据加密也能用于数字签名的算法.该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困 难,因此可以将乘积公开作为加密密钥,即公钥,而两个大素数组合成私钥.公钥是可发布的供任何人使用,私钥则为自己所有,供解密之用. RSA算法原理 1.随机选择两个大质数p和q,p不等于q,计算N=pq: 2.选择一个大于1小于N的自然数e,e必须与(p-1)(q-1)互素. 3.用公式计算出d:

  • SpringBoot实现接口数据的加解密功能

    一.加密方案介绍 对接口的加密解密操作主要有下面两种方式: 自定义消息转换器 优势:仅需实现接口,配置简单. 劣势:仅能对同一类型的MediaType进行加解密操作,不灵活. 使用spring提供的接口RequestBodyAdvice和ResponseBodyAdvice 优势:可以按照请求的Referrer.Header或url进行判断,按照特定需要进行加密解密. 比如在一个项目升级的时候,新开发功能的接口需要加解密,老功能模块走之前的逻辑不加密,这时候就只能选择上面的第二种方式了,下面主要

随机推荐