一、背景

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

二、解决方案

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

  • 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));
}
}

注意️:

  1. @MappedTypes:表示该处理器处理的java类型是什么。
  2. @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、编写后台代码

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

后台代码比较简单,直接查看 https://gitee.com/huan1993/spring-cloud-parent/tree/master/mybatis/mybatis-typehandler-encrypt
贴一个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加解密数据的更多相关文章

  1. 微信公众号-加解密数据demo坑

    demo里面的MsgSignature作为url参数一部分了,demo也不更新下 坑爹的微信! 解密信息部分 include_once "wxBizMsgCrypt.php"; $ ...

  2. T-SQL问题解决集锦——数据加解密

    原文:T-SQL问题解决集锦--数据加解密 以下代码已经在SQLServer2008上的示例数据库测试通过 问题一:如何为数据进行加密与解密,避免使用者窃取机密数据? 对于一些敏感数据,如密码.卡号, ...

  3. java安全与加解密

    1 安全 安全性相关内容分为认证.授权和审计(发现安全问题时可以查看相关历史记录) 用户认证 java API表示主体的是javax.security.auth.Subject类型,表示用户身份标识的 ...

  4. 痞子衡嵌入式:SNVS Master Key仅在i.MXRT10xx Hab关闭时才能用于DCP加解密

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT系列中数据协处理器DCP使用SNVS Master Key加解密的注意事项. i.MXRT不仅仅是处理性能超强的MCU,也是 ...

  5. Mybatis使用TypeHandler实现数据的加解密转换

    参考: MyBatis之TypeHandler: https://www.cnblogs.com/yulinfeng/p/5991170.html   前段时间收到这么个需求:为安全起见,要求在数据库 ...

  6. 从零开始实现一个MyBatis加解密插件

    作者:vivo 互联网服务器团队- Li Gang 本篇文章介绍使用MyBatis插件来实现数据库字段加解密的过程. 一.需求背景 公司出于安全合规的考虑,需要对明文存储在数据库中的部分字段进行加密, ...

  7. 以Crypto++实现RSA加解密二进制数据

    网上一大片讲怎么加解密字符串的,找了大半天也没找到讲加解密二进制数据的,于是自己研究了下,分享给大家. 加解密函数: #include <rsa.h> #include <randp ...

  8. T-SQL问题解决集锦——数据加解密(2)

    原文:T-SQL问题解决集锦--数据加解密(2) 问题三.如何让指定用户可以对数据表进行Truncate操作? Truncate在对大表全删除操作时,会明显比Delete语句更快更有效,但是因为它不需 ...

  9. 使用JDK中的安全包对数据进行加解密

    本文以使用DES对称加密算法为例使用jdk对数据进行加密解密. 首先需要了解Provider类,它是jdk引入的密码服务提供者概念,实现了Java安全性的一部分或者全部.Provider 可能实现的服 ...

随机推荐

  1. 【机器学习|数学基础】Mathematics for Machine Learning系列之线性代数(1):二阶与三阶行列式、全排列及其逆序数

    @ 目录 前言 二阶与三阶行列式 二阶行列式 三阶行列式 全排列及其逆序数 全排列 逆序数 结语 前言 Hello!小伙伴! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出-   自我介绍 ...

  2. Vue跨域问题解决

    项目根目录下创建vue.config.js module.exports = { devServer: { proxy: { //配置跨域 '/api': { //这里是真实的后台接口 target: ...

  3. ☕【Java技术指南】「并发编程专题」针对于Guava RateLimiter限流器的入门到精通(含实战开发技巧)

    并发编程的三剑客 在开发高并发系统时有三剑客:缓存.降级和限流. 缓存 缓存的目的是提升系统访问速度和增大系统处理容量. 降级 降级是当服务出现问题或者影响到核心流程时,需要暂时屏蔽掉,待高峰或者问题 ...

  4. 机器学习——逻辑回归(Logistic Regression)

    1 前言 虽然该机器学习算法名字里面有"回归",但是它其实是个分类算法.取名逻辑回归主要是因为是从线性回归转变而来的. logistic回归,又叫对数几率回归. 2 回归模型 2. ...

  5. 使用metaweblog API实现通用博客发布 之 本地图片自动上传以及替换路径

    使用metaweblog API实现通用博客发布 之 本地图片自动上传以及替换路径 通过metaweblog API 发布博文的时候,由于markdown中的图片路径是本地路径,将导致发布的文章图片不 ...

  6. 虚拟机乌班图系统安装 VMware tools 工具

    在VMware虚拟机中安装完毕Linux操作系统之后,我们经常会发现桌面不能全屏显示或者windows主机系统与linux操作系统之间无法创建共享文件夹.这是因为我们还没有安装VMware tools ...

  7. python学习笔记(八)-模块

    大型python程序以模块和包的形式组织.python标准库中包含大量的模块.一个python文件就是一个模块.1.标准模块 python自带的,不需要你安装的2.第三方模块 需要安装,别人提供的. ...

  8. requests + 正则表达式 获取 ‘猫眼电影top100’。

    使用 进程池Pool 提高爬取数据的速度. 1 # !/usr/bin/python 2 # -*- coding:utf-8 -*- 3 import requests 4 from request ...

  9. P4332-[SHOI2014]三叉神经树【LCT】

    正题 题目链接:https://www.luogu.com.cn/problem/P4332 题目大意 给出\(n\)个点的一棵有根三叉树,保证每个点的儿子个数为\(3\)或者\(0\),每个叶子有一 ...

  10. CF803G-Periodic RMQ Problem【离散化,线段树,ST表】

    正题 题目链接:https://www.luogu.com.cn/problem/CF803G 题目大意 一个长度为\(n\)的序列\(a\)复制\(k\)份连接,要求支持 区间赋值 区间查询最小值 ...