Springboot 对于数据库字段加密方案(此方案是对字符串处理的方案)
背景:在erp开发中,有些用户比较敏感数据库里的数据比较敏感,系统给用户部署后,公司也不想让任何人看到数据,所以就有了数据库字段加密方案。
技术 spring boot + mybatisplus 3.3.1
mybatisplus 实际提供了 字段加密方案
第一 他要钱
第二 他是在实体类上加注解 满足不了我们的需求

我们的整体需求是
用户可以自定义配置字段
在系统设置里 有个 字段加密 菜单
- 点击某个表单 然后显示这个表单所需要的字段
2.勾选 某个字段 这个字段 就会激活 再提交 更新表单的时候 这个字段就会加密处理
比如 系统管理 字段加密 他点击了请假表单 然后勾选 请假事由 字段加密
然后 公司的员工再次提交表单的时候 请假事由 就会被加密 。
这个需求 用户再页面上操作 我们是不需要改代码的 。
如果利用实体类加注解方案 肯定满足不了 因为 每个用户加密的字段不一样,
鬼知道 加密注解要加在哪个实体类上
我们的系统 表单 和表单的字段 都定义在数据库里 所以 可以自由选择 表单和字段
这个根据各自系统自行修改
下面直接分享 加密的代码和思路 。原理我就不再说 ,用到的知识 自行百度即可
第一步 : 首先把用户勾选需要加密的 字段 缓存到redis 减少数据库查询
// 这段代码 就不分享了 自由编写
根据表名 获取 需要加密的字段
List<String> stringList= BaseDataUtil.getFieldPassword(insertSql.getTableName());
第二步:
引入加密依赖
<!--对数据库字段进行加密、脱敏--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.3</version></dependency>
第三步:
配置文件 配置

第四步 编写加密方案 利用的是 框加下的这个类 BaseTypeHandler
对于这个类的介绍 自行百度
自定义一个类 然后继承 这个类 BaseTypeHandler
重写 父类方法
package com.erp.init.handlers;import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import com.erp.init.utils.BaseDataUtil;
import org.apache.ibatis.logging.jdbc.PreparedStatementLogger;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;import java.lang.reflect.Proxy;
import java.nio.charset.StandardCharsets;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** User: Json* <p>* Date: 2023/11/14**/
public class EncryptHandler extends BaseTypeHandler<String> {/*** 线上运行后勿修改,会影响已加密数据解密*/private static final byte[] KEYS = "shc987654321camp".getBytes(StandardCharsets.UTF_8);private static final String dataWithPrefix = "A:Json";/*** 设置参数*/@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {if (StringUtils.isEmpty(parameter)) {ps.setString(i, null);return;}// 获取动态代理类的 InvocationHandlerPreparedStatementLogger handler =(PreparedStatementLogger) Proxy.getInvocationHandler(ps);PreparedStatement preparedStatement= handler.getPreparedStatement();MetaObject stmtMetaObj = SystemMetaObject.forObject(preparedStatement);String sql = stmtMetaObj.getValue("sql").toString();//System.out.println("sql:"+sql);SqlResult updateSql= updateSql(sql);if(!ObjectUtils.isEmpty(updateSql)){if(updateSql.getColumnNames().size()>(i-1)){// System.out.println("更新数据:"+updateSql);
// System.out.println(i+"===>"+updateSql.getColumnNames().get(i-1));List<String> stringList= BaseDataUtil.getFieldPassword(updateSql.getTableName());if (!CollectionUtils.isEmpty(stringList) &&!CollectionUtils.isEmpty(updateSql.getColumnNames()) &&stringList.contains(updateSql.getColumnNames().get(i-1))) {AES aes = SecureUtil.aes(KEYS);String encrypt = aes.encryptHex(parameter);ps.setString(i,dataWithPrefix+ encrypt);} else {ps.setString(i, parameter);}}else{ps.setString(i, parameter);}}SqlResult insertSql=insetSQl(sql);if(!ObjectUtils.isEmpty(insertSql)){if(insertSql.getColumnNames().size()>(i-1)){// System.out.println("新增数据:"+insertSql);
// System.out.println(i+"===>"+insertSql.getColumnNames().get(i-1));List<String> stringList= BaseDataUtil.getFieldPassword(insertSql.getTableName());if (!CollectionUtils.isEmpty(stringList) &&!CollectionUtils.isEmpty(insertSql.getColumnNames()) &&stringList.contains(insertSql.getColumnNames().get(i-1))) {AES aes = SecureUtil.aes(KEYS);String encrypt = aes.encryptHex(parameter);ps.setString(i, dataWithPrefix+ encrypt);} else {ps.setString(i, parameter);}}else{ps.setString(i, parameter);}}if(ObjectUtils.isEmpty(insertSql) && ObjectUtils.isEmpty(updateSql) ){ps.setString(i, parameter);}}/*** 获取值*/@Overridepublic String getNullableResult(ResultSet rs, String columnName) throws SQLException {return decrypt(rs.getString(columnName),columnName,rs.getMetaData().getTableName(1));}/*** 获取值*/@Overridepublic String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {// return null;return rs.getString(columnIndex);}/*** 获取值*/@Overridepublic String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {// return null;return cs.getString(columnIndex);}public String decrypt(String value,String columnName,String tableName) {// return value;if (null == value) {return null;}List<String> stringList= BaseDataUtil.getFieldPassword(tableName);if(CollectionUtils.isEmpty(stringList)){return value;}if (value.startsWith(dataWithPrefix) && stringList.contains(columnName)) {// 是新数据,去掉前缀String decryptedData = value.substring(dataWithPrefix.length());return SecureUtil.aes(KEYS).decryptStr(decryptedData);} else {return value;}}public static SqlResult updateSql(String sql) {// 假设你已经有了sql字符串// String sql = "UPDATE your_table SET column1 = value1, column2 = value2 WHERE condition";// 匹配UPDATE语句Pattern updatePattern = Pattern.compile("UPDATE\\s+([^\\s]+)\\s+SET\\s+([^\\s]+\\s*=\\s*[^,]+(,\\s*[^\\s]+\\s*=\\s*[^,]+)*)\\s+WHERE\\s+(.+)");Matcher updateMatcher = updatePattern.matcher(sql);// 如果是UPDATE语句if (updateMatcher.matches()) {String tableName = updateMatcher.group(1); // 获取表名String setClause = updateMatcher.group(2); // 获取SET子句// 提取更新的字段名List<String> columnNames = extractColumnNames(setClause);// 返回表名和字段名的信息return new SqlResult(tableName, columnNames);}return null;}private static List<String> extractColumnNames(String setClause) {List<String> columnNames = new ArrayList<>();String[] columns = setClause.split("\\s*,\\s*");for (String column : columns) {String[] parts = column.split("\\s*=\\s*");String columnName = parts[0].trim();columnNames.add(columnName);}return columnNames;}private static List<String> extractColumnNamesInsert(String columnsClause) {String[] columns = columnsClause.split("\\s*,\\s*");List<String> columnNames = new ArrayList<>();for (String column : columns) {columnNames.add(column.trim());}return columnNames;}public static SqlResult insetSQl(String sql) {// 假设你已经有了sql字符串// String sql = "INSERT INTO your_table (column1, column2) VALUES (value1, value2)";// 匹配INSERT语句Pattern insertPattern = Pattern.compile("INSERT\\s+INTO\\s+([^\\s]+)\\s*\\(([^)]+)\\)\\s*VALUES\\s*\\(([^)]+)\\)");Matcher insertMatcher = insertPattern.matcher(sql);// 如果是INSERT语句if (insertMatcher.matches()) {String tableName = insertMatcher.group(1); // 获取表名String columnsClause = insertMatcher.group(2); // 获取列名的部分// String valuesClause = insertMatcher.group(3); // 获取值的部分// 提取新增的字段名和对应的值List<String> columnNames = extractColumnNamesInsert(columnsClause);// 返回表名、字段名和对应值的信息return new SqlResult(tableName, columnNames);}return null;}}
第五步:
把这个类注册到配置文件中
package com.erp.init.mybatisplus;import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.erp.init.handlers.EncryptHandler;
import org.apache.ibatis.type.JdbcType;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** User: Json* <p>* Date: 2023/11/15**/
@Configuration
public class MyBatisConfig {@Beanpublic ConfigurationCustomizer configurationCustomizer() {return configuration -> {//String.class, JdbcType.VARCHAR 这个是 只对 字符串进行处理// int float 的加密 根据字符串再扩展一个类就行了 configuration.getTypeHandlerRegistry().register(String.class, JdbcType.VARCHAR, new EncryptHandler());// 注册其他类型处理器};}
}
这要编写后 每次 mybatisplus 调用 新增 和 更新 批量更新 批量操作 都会触发这里的代码
实现字段加解密
相关文章:
Springboot 对于数据库字段加密方案(此方案是对字符串处理的方案)
背景:在erp开发中,有些用户比较敏感数据库里的数据比较敏感,系统给用户部署后,公司也不想让任何人看到数据,所以就有了数据库字段加密方案。 技术 spring boot mybatisplus 3.3.1 mybatisplus 实际提供了 字段加密方案 第一 他…...
[C++]:8.C++ STL引入+string(介绍)
C STL引入string(介绍) 一.STL引入:1.什么是STL2.什么是STL的版本:2-1:原始版本:2-2:P. J 版本:2-3:RW 版本:2-4:SGL版本: 3.STL 的六大组件&…...
C++基础从0到1入门编程(三)
系统学习C 方便自己日后复习,错误的地方希望积极指正 往期文章: C基础从0到1入门编程(一) C基础从0到1入门编程(二) 参考视频: 1.黑马程序员匠心之作|C教程从0到1入门编程,学习编程不再难 2.系统…...
[Jenkins] 物理机 安装 Jenkins
这里介绍Linux CentOS系统直接Yum 安装 Jenkins,不同系统之间类似,操作命令差异,如:Ubuntu用apt; 0、安装 Jenkins Jenkins是一个基于Java语言开发的持续构建工具平台,主要用于持续、自动的构建/测试你的软…...
设计模式 -- 适配器模式(Adapter Pattern)
适配器模式:属于结构型模式,结合了两个独立接口的功能,作为 两个不兼容的接口之间的桥梁 。 介绍 意图:将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。主要…...
Axios传值的几种方式
<body><script src"https://unpkg.com/axios/dist/axios.min.js"></script></body> axios基本使用 默认是get请求 注意:get请求无请求体,可以有body,但是不建议带 使用get方式进行无参请求 <script>axios(…...
git pull 报错 error object file is empty , The remote end hung up unexpectedly
报错原因分析:git pull的时候服务器在重启,导致git文件损坏 方法来源: 解决git错误: error object file is empty , The remote end hung up unexpectedly-CSDN博客 亲测有效 find .git/objects/ -type f -empty | xargs rm git fetch -p…...
手机数码类展示预约小程序效果如何
对于一家手机数码/电脑品牌来说,研发产品或衍生产品不少,通常会通过线上商城进行售卖。十年以来,流量成本逐渐增加,获客不易也难以寻找到合适的渠道,即使通过广告形式也因缺乏创意而耗时耗力,效果不佳。 同…...
图神经网络:消息传递算法
一、说明 图网络-GNN(Graph Neural Networks)是近几年研究的主题之一,虽不及深度神经网络那么火爆,但在一些领域,如分子化学方面是不得不依赖的理论。本文就一些典型意义的图神经网络消息传递展开阐述。 二、图网络简述…...
安全+Linux!IBM新一代大型机Z14全新发布
导读本周,以“架构 人机同行”为主题的IBM Systems创行者高峰论坛在北京召开,IBM全球及大中华区硬件系统部负责人,金融、医疗、制造等领域的企业、合作伙伴共与这一年度盛会,探讨认知时代下的基础架构技术趋势及IBM硬件系统业务的…...
Java中的局部变量和成员变量的区别
局部变量和成员变量的区别 区别1:代码中位置不同 成员变量:类中方法外定义的变量 局部变量:方法中定义的变量 代码块中定义的变量 区别2:代码的作用范围 成员变量:当前类的很多方法 局部变量:当前一…...
基于C++实现循环赛日程表(分治算法)
一、问题描叙 设有n2^k个运动员,要进行网球循环赛。现在要设计一个满足以下要求的比赛日程表 每个选手必须与其他n-1个选手各赛一场每个选手一天只能赛一次循环赛一共进行n-1天 二、问题分析 按此要求可将比赛日程表设计成n行n-1列的表,在表中第 i 行…...
基于uni-app的汽车租赁app的设计与实现
1.项目背景及意义 项目背景: 随着人们生活水平的提高,汽车租赁服务在城市中变得越来越普及。传统的租车方式存在一些问题,比如租车流程繁琐、费用不透明、选择有限等。因此,开发一款基于uni-app的汽车租赁app成为了满足用户需求…...
3.8-镜像的发布
如果我们想将image push到docker hub里面,那么我们的image的名字一定要是这种格式:docker hub id/imageName,例如:lvdapiaoliang/hello-docker docker hub个人账户设置地址: 在push之前要先登录: docker l…...
Navicat 基于 GaussDB 主备版的快速入门
Navicat Premium(16.2.8 Windows版或以上) 已支持对GaussDB 主备版的管理和开发功能。它不仅具备轻松、便捷的可视化数据查看和编辑功能,还提供强大的高阶功能(如模型、结构同步、协同合作、数据迁移等),这…...
String的字符串拼接
java中 String a “123” “234”; String b “123”; String c b “234”; 其中a和c的区别是什么? a c 为什么为false 在Java中,字符串的处理特别是涉及到字符串常量和字符串变量的连接时,会涉及到字符串池(String Pool&a…...
反渗透水处理成套设备有哪些
反渗透水处理成套设备主要包括反渗透装置、预处理系统、控制系统等部分。 反渗透装置:反渗透水处理设备的核心部分,由反渗透膜、压力容器、膜组件等组成。反渗透膜是一种高分子材料制成的半透膜,能够截留水中的溶解盐、有机物、细菌等杂质&a…...
DPC15 国产带有 SPI 接口的独立 CAN 控制器兼容替代MCP2551
DPC15是一款独立控制器局域网络(Controller Area Network,CAN)协议控制器,完全支持CAN V2.0B技术规范。该器件能发送和接收标准和扩展数据帧以及远程帧。 DPC15自带的两个验收屏蔽寄存器和六个验收滤波寄存器可以过滤掉不想要的报…...
【ELK01】ELK简介以及ElasticSearch安装、ES客户端工具-Head安装、报错问题整理
有一段时间没有更新这个专栏了,最近在用ELK相关的技术,今天开始写一下ELK的系列的内容,与大家共同学习 一、什么是ELK ELK 是elastic公司提供的一套完整的日志收集以及展示的解决方案,是三个产品的首字母缩写,分别是ElasticSearch、Logstash 和 Kibana。 1. E-ELASTICS…...
根据音频绘制频谱
根据音频链接绘制频谱图 封装 // 可以这样使用 也可以 import { AudioContext } from standardized-audio-context; const getAudioContext window.AudioContext ||window.webkitAudioContext ||window.mozAudioContext ||window.msAudioContext;const clearArr []export c…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...
《Offer来了:Java面试核心知识点精讲》大纲
文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...
