扔掉工具类!MyBatis 一个简单配置搞定加密、解密,好用!

2023-11-17

6cb2c0490a10b40264143abcd5a23815.jpeg

程序员的成长之路

互联网/程序员/技术/资料共享 

关注

阅读本文大概需要 3.5 分钟。

来自:https://juejin.cn/post/6963811586184052767

目录

  • 一、背景

  • 二、解决方案

  • 三、需求

  • 四、实现思路

  • 五、实现代码


一、背景

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


二、解决方案

由于我们系统中使用了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层的截图。

9800a2a7177cfe7113c7243915c86b10.jpeg

6、测试结果

09d2dcecdc76e2ed7da589995e002ca1.jpeg

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

五、实现代码

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

<END>

推荐阅读:

员工将密码设为“123456”,导致AMD被盗450GB数据

不好意思,list.contain 去重该换换了!

互联网初中高级大厂面试题(9个G)
内容包含Java基础、JavaWeb、MySQL性能优化、JVM、锁、百万并发、消息队列、高性能缓存、反射、Spring全家桶原理、微服务、Zookeeper......等技术栈!
⬇戳阅读原文领取!                                  朕已阅
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

扔掉工具类!MyBatis 一个简单配置搞定加密、解密,好用! 的相关文章

随机推荐

  • SpringBoot生成二维码

    目录 Zxing原生方式 添加依赖 二维码生成工具类 添加Controller 添加测试页面 使用postman测试效果 Hutool的方式 添加依赖 创建QRCodeService 添加Controller 效果测试 我们使用两种方式 去
  • mutex_init() / mutex_lock() / mutex_unlock()

    请求 1 初始化互斥体 mutex init 2 获得互斥体 mutex lock 3 释放互斥体 mutex unlock 1 mutex init 注意mutex使用之前都需要先init void mutex init struct m
  • 最小交换次数-华为OD

    整数数组nums 整数k 输出将数组A中小于k的整数组合到一起的最小交换次数 组合在一起是指满足条件的数字相邻 不要求相邻后在数组中的位置 样例1 nums 1 3 1 4 0 k 2 输出 1 解析 交换第一个1和4 样例2 nums 0
  • Django跳坑:objects.all()、objects.get()与objects.filter()之间的区别

    文章目录 1 三者之间的区别 2 获取数据 2 1 取单个数据 3 序列化 3 1 QuerySet序列化 3 2 models序列化 1 三者之间的区别 all返回的是QuerySet对象 程序并没有真的在数据库中执行SQL语句查询数据
  • Github账号开启账号双重验证

    Github账号开启账号双重验证 发现问题 解决步骤 插件使用 发现问题 今天在浏览开源项目的时候 突然Github有个提示我要在10月12日前开启双重验证 说是不完成的话 到时候的Github账号会受到限制 如下图 通过设置也可以找到 解
  • win11设置任务栏不合并的方法教程

    win11系统的任务栏窗口默认设置是合并的 有些小伙伴表示用起来还不太习惯 那么win11任务栏怎么设置不合并呢 下面小编为大家分享下win11设置任务栏不合并的方法 感兴趣的小伙伴一起来看看吧 win11设置任务栏不合并的方法教程 1 我
  • Elasticsearch学习笔记2:ES核心概念 -- 索引、倒排索引、类型、文档

    一 ES和关系型数据库的对比 Elasticsearch Relational DB 索引 index 数据库 database 类型 types 表 tables 文档 documents 行 rows 字段 fields 列 colum
  • OLED透明屏报价:实现高质量展示的成本与选择

    引言 OLED透明屏作为商业展示领域的新兴技术 受到了广泛的关注和需求 然而 对于OLED透明屏的报价 人们常常存在疑虑 在这篇文章中 尼伽将详细解析OLED透明屏报价的构成和选择因素 希望能帮助您更好呢地了解OLED透明屏 一 OLED透
  • vue中textarea高度的设置_vue中textarea自适应高度

    HTML data return pltxt 评论 inputText isHeight true minHeight 0 methods autoTextarea var extra 0 设置光标与输入框保持的距离 默认0 maxHeig
  • SQL操作

    一 查询语句 1 基本查询 SELECT FROM lt 表名 gt 查询表的所有行 SELECT FROM students 2 条件查询 SELECT FROM lt 表名 gt WHERE lt 条件表达式 gt 查询分数在80分以上
  • vscode+phpstudy连接使用mysql(解决phpstudy中mysql无法启动的问题)

    vscode phpstudy连接使用mysql 解决phpstudy中mysql无法启动的问题 使用vscode phpstudy配置php开发环境网上很文章都是挺好的 都成功解决了我的问题 但是对于使用mysql方面始终找不到很系统的文
  • 数据结构系列——先进先出队列queue

    本期主题 先进先出队列实现 目录 1 队列定义 2 实现一个简单的队列以及分析 1 代码实现分析 2 code 3 优缺点分析 3 循环队列实现 1 循环队列原理 2 循环队列实现分析 3 code 1 队列定义 队列是什么 定义 一个先进
  • unity,网格碰撞器(Mesh Collider)

    介绍 网格碰撞器 Mesh Collider 在实现物理碰撞检测时 可以自动检测凸面 但是它并不总是能够准确地生成凸多面体 这是因为在将一个网格模型转换为凸多面体的过程中 可能会出现模型内部空洞或者交叉的情况 这些情况会导致凸多面体的生成失
  • H5页面长按识别二维码

    vue 写的H5 内嵌在小程序上 img src 图片路径 style width 200px height 200px 直接在微信访问长按就可以实现 微信原生直接写长按识别二维码 aaa e let img e target datase
  • 八. springboot 的指标监控 (3、定制 Endpoint )

    3 定制 Endpoint 3 1 定制 Health 信息 import org springframework boot actuate health Health import org springframework boot act
  • http、https以及状态码超全详解

    文章目录 HTTP 概念 作用 http 请求 http 头部 http 连接 各版本的区别 http1 0 http1 1 http2 0 http3 0 HTTPS 概念 作用 工作原理 优点 缺点 http 和 https 区别 ht
  • [网络安全自学篇] 八.Web漏洞及端口扫描之Nmap、ThreatScan和DirBuster原理详解

    Web渗透技术的核心是发现Web漏洞 发现漏洞有手工和软件自动化扫描两种方式 对于用户验证漏洞 用户凭证管理问题 权限特权及访问控制漏洞 缓存漏洞 跨站脚本漏洞 加密漏洞 路径切换漏洞 代码注入漏洞 配置漏洞 数据和信息泄露 输入验证码漏洞
  • CA证书服务搭建

    准备一 域服务搭建 步骤一 搭建CA证书服务器 设置固定IP地址 192 168 0 与主机名 DC 打开服务器管理器 gt 点击添加角色和功能 步骤二 一路回车到达选择服务器角色位置 选中Active Directory域服务与Activ
  • 动态库装载及 dlsym的RTLD_NEXT参数详解

    在看公司spp框架代码的时候发现了如下一段宏定义 其中的dlsym函数及其RTLD NEXT参数的含义不是很明白 于是网上搜了下这里做个记录 define mt hook syscall name do if g mt syscall ta
  • 扔掉工具类!MyBatis 一个简单配置搞定加密、解密,好用!

    程序员的成长之路 互联网 程序员 技术 资料共享 关注 阅读本文大概需要 3 5 分钟 来自 https juejin cn post 6963811586184052767 目录 一 背景 二 解决方案 三 需求 四 实现思路 五 实现代