SpringDataJpa-字段加解密存储

SpringDataJpa-字段加解密存储

    • 背景
    • 场景
    • 实现
      • 类型转换器
        • 实体类修改
      • Crypto 注解
      • AOP
    • 目前可使用场景
    • 注意

背景

遇到一个需求,对数据库中的某些字段进行加密存储,但是在各个服务流转中,需要是解密状态的。框架使用的是JPA。

Spring 提供了 AttributeConverter<T,R> 用来将实体属性与数据库字段之间的逻辑转换。换日期格式转换这种。但是我们这边需要改变类型,只需要改变类型的值。

但是使用原生SQL的时候用加密字段进行查询的化,是不会使用类型转换器的。所以我这里增加了一个注解,来拦截标有该注解的参数,然后将参数的值进行修改,然后再进行查询。这里实现的化使用的是 AOP

场景

  • 使用实体类进行查询,插入,更新,删除(HQL
    • 使用加密字段进行查询的(使用类型转换器实现)
    • 返回为实体类 (使用类型转换器实现)
  • 使用原生sql 进行查询,插入,更新,删除
    • 返回出来的是 map 结构(需要单独处理)
    • 返回为实体类 (使用类型转换器实现)
    • 使用加密字段进行查询的(AOP + 注解实现

实现

类型转换器

实现AttributeConverter

@Slf4j
public class CryptoConvert implements AttributeConverter<String,String> {/*** 存入数据库前进行的转化操作* @param attribute* @return*/@Overridepublic String convertToDatabaseColumn(String attribute) {String encode = CryptoUtil.encode(attribute);log.info("oldValue:{},newValue:{}",attribute,encode);return encode;}/*** 取出数据库后进行的转化操作* @param dbData* @return*/@Overridepublic String convertToEntityAttribute(String dbData) {String decode = CryptoUtil.decode(dbData);log.info("oldValue:{},newValue:{}",dbData,decode);return decode;}
}
实体类修改
@Column(name="remark")
// 增加类型转换器,标注该字段需要使用类型转换器处理
@Convert(converter = CryptoConvert.class)
private java.lang.String remarks;

Crypto 注解

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Crypto {
}

AOP

尝试使用@Before但是不能修改参数的值,所以这里使用@Around

@Slf4j
@Component
@Aspect
public class CryptoAspect {/*** 针对带有@Crypto注解的参数进行加密* @param joinPoint* @return* @throws Throwable*/@Around(value = "execution(* *(..,@Crypto (String),..))")public Object encrypt(ProceedingJoinPoint joinPoint) throws Throwable {MethodSignature signature = (MethodSignature) joinPoint.getSignature();Annotation[][] parameterAnnotations = signature.getMethod().getParameterAnnotations();Object[] oldArgs = joinPoint.getArgs();Object[] newArgs = Arrays.copyOf(oldArgs, oldArgs.length);for (int i = 0; i < newArgs.length; i++) {if (Objects.isNull(newArgs[i])) {continue;}if(!(newArgs[i] instanceof String)){continue;}Annotation[] parameterAnnotation = parameterAnnotations[i];if (ArrayUtils.isEmpty(parameterAnnotation)) {continue;}for (Annotation annotation : parameterAnnotation) {if (Crypto.class.equals(annotation.annotationType())) {String str = (String) newArgs[i];String encode = CryptoUtil.encode(str);newArgs[i] = encode;}}}log.info("oldArgs:{} newArgs:{}",oldArgs,newArgs);// 使用解密后的参数调用对应方法return joinPoint.proceed(newArgs);}
}

目前可使用场景

// 1.JPA 使用方法名操作数据库                  remarks 为需要加密查询的字段 
List<Model> findByRemarks(@Param(value = "remarks") String remarks);// 2.JPA 使用 @Query 注解并使用 HQL 操作数据库   remarks 为需要加密查询的字段 
@Query("select C FROM Model C where C.remarks = ?1")
List<Model> findByRemarks2(@Param(value = "remarks") String remarks);// 3.JPA 使用 @Query 注解并使用 原生SQL 操作数据库   remarks 为需要加密查询的字段  (hibernate 查出数据库时也会使用类型转换器所以不再单独解密)
@Query(value = "select * from t_model where remark = ?1",nativeQuery = true)
List<Model> findByRemarks3(@Crypto @Param(value = "remarks") String remarks);// 4.使用 Query + HQL   及可实现(hibernate 查出数据库时也会使用类型转换器所以不再单独解密)
@Override
public List<Model> getRemarks2(String remarks) {Query query = em.createQuery("select C FROM Model C where C.remarks = ?1",AccountBindHistory.class);query.setParameter(1, remarks);List<Model> resultList = query.getResultList();return resultList;
}// 5.使用 Query + SQL  这个需要在入口处添加@Crypto 及可实现(hibernate 查出数据库时也会使用类型转换器所以不再单独解密)
@Override
public List<Model> getRemarks(@Crypto String remark) {Query query = em.createNativeQuery("select * from t_model where remark = ?",AccountBindHistory.class);query.setParameter(1, remark);List<Model> resultList = query.getResultList();return resultList;
}// em.createNativeQuery 在创建Query的时候需要指定操作的映射类型// 6.Spring-data-rest 生成的接口也支持自动加解密

注意

  1. 加密方式需要使用**对称加密,**也就是可以将明文转换出来的算法。
  2. 数据库中已有的数据需要进行处理,也就是需要加密。这样可以保证查询是与后入库的数据都能正常解密,

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/491675.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kubernetes学习-使用metrics-server监控集群资源和查看日志

kubernetes学习-使用metrics-server监控集群资源和查看日志 一 、简介 Metrics Server 是一个用于 Kubernetes 集群的监控工具&#xff0c;它用于收集、存储和提供关于集群中各种资源的度量数据。Metrics Server 是 Kubernetes 中一个核心的指标收集器&#xff0c;可以提供关…

如何使用git新建本地仓库并关联远程仓库的步骤(详细易懂)

一、新建本地仓库并关联远程仓库的步骤 新建本地仓库 打开终端&#xff08;在 Windows 上是命令提示符或 PowerShell&#xff0c;在 Linux 和Mac上是终端应用&#xff09;&#xff0c;进入你想要创建仓库的目录。例如&#xff0c;如果你想在桌面上创建一个名为 “my - project”…

【小沐学GIS】基于C++绘制三维数字地球Earth(OpenGL、glfw、glut、QT)第三期

&#x1f37a;三维数字地球系列相关文章如下&#x1f37a;&#xff1a;1【小沐学GIS】基于C绘制三维数字地球Earth&#xff08;456:OpenGL、glfw、glut&#xff09;第一期2【小沐学GIS】基于C绘制三维数字地球Earth&#xff08;456:OpenGL、glfw、glut&#xff09;第二期3【小沐…

【机器学习】在向量的流光中,揽数理星河为衣,以线性代数为钥,轻启机器学习黎明的瑰丽诗章

文章目录 线性代数入门&#xff1a;机器学习零基础小白指南前言一、向量&#xff1a;数据的基本单元1.1 什么是向量&#xff1f;1.1.1 举个例子&#xff1a; 1.2 向量的表示与维度1.2.1 向量的维度1.2.2 向量的表示方法 1.3 向量的基本运算1.3.1 向量加法1.3.2 向量的数乘1.3.3…

《拉依达的嵌入式\驱动面试宝典》—C/CPP基础篇(一)

《拉依达的嵌入式\驱动面试宝典》—C/CPP基础篇(一) 你好&#xff0c;我是拉依达。 感谢所有阅读关注我的同学支持&#xff0c;目前博客累计阅读 27w&#xff0c;关注1.5w人。其中博客《最全Linux驱动开发全流程详细解析&#xff08;持续更新&#xff09;-CSDN博客》已经是 Lin…

【Linux】—简单实现一个shell(myshell)

大家好呀&#xff0c;我是残念&#xff0c;希望在你看完之后&#xff0c;能对你有所帮助&#xff0c;有什么不足请指正&#xff01;共同学习交流哦&#xff01; 本文由&#xff1a;残念ing原创CSDN首发&#xff0c;如需要转载请通知 个人主页&#xff1a;残念ing-CSDN博客&…

数据结构day5:单向循环链表 代码作业

一、loopLink.h #ifndef __LOOPLINK_H__ #define __LOOPLINK_H__#include <stdio.h> #include <stdlib.h>typedef int DataType;typedef struct node {union{int len;DataType data;};struct node* next; }loopLink, *loopLinkPtr;//创建 loopLinkPtr create();//…

利用CNN与多尺度特征、注意力机制的融合实现低分辨率人脸表情识别,并给出模型介绍与代码实现

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下利用CNN与多尺度特征、注意力机制的融合实现低分辨率人脸表情识别&#xff0c;并给出模型介绍与代码实现。在当今社会&#xff0c;人脸识别技术已广泛应用&#xff0c;但特定场景下的低质量图像仍是一大挑战。 低分…

Scala—“==“和“equals“用法(附与Java对比)

Scala 字符串比较—""和"equals"用法 Scala 的 在 Scala 中&#xff0c; 是一个方法调用&#xff0c;实际上等价于调用 equals 方法。不仅适用于字符串&#xff0c;还可以用于任何类型&#xff0c;并且自动处理 null。 Demo&#xff1a; Java 的 在 J…

驱动开发-入门【1】

1.内核下载地址 Linux内核源码的官方网站为https://www.kernel.org/&#xff0c;可以在该网站下载最新的Linux内核源码。进入该网站之后如下图所示&#xff1a; 从上图可以看到多个版本的内核分支&#xff0c;分别为主线版本&#xff08;mainline&#xff09;、稳定版本&#…

Android Room 数据库使用详解

一、Room介绍 Android Room 是 Google 提供的一个 Android 数据持久化库&#xff0c;是 Android Jetpack 组成部分之一。它提供了一个抽象层&#xff0c;使得 SQLite 数据库的使用更为便捷。通过 Room&#xff0c;开发者可以轻松地操作数据库&#xff0c;不需要直接编写繁琐的…

使用k6进行Redis基准测试

1.安装环境 前提条件&#xff1a;已经安装go 安装xk6 go install go.k6.io/xk6/cmd/xk6latest 安装成功会在GOPATH目录生成xk6可执行文件 安装xk6-redis 切换到xk6工作目录&#xff0c;执行如下命令 cd /Users/wan/go/bin ./xk6 build --with github.com/grafana/xk6-re…

【期末复习】JavaEE(上)

1. Java EE概述 开发环境及开发工具 1.1. HTTP协议 开发模式 2. Java Web技术 JSP技术 2.1. Servlet技术 2.1.1. HttpServletRequest 常用方法 2.1.2. HttpServletRequest 请求乱码 tomcat7 及以下&#xff08;对于每个参数单独进行编码转换&#xff09;&#xff1a; 2.…

KeyFormer:使用注意力分数压缩KV缓存

Keyformer: KV Cache Reduction through Key Tokens Selection for Efficient Generative Inference 202403&#xff0c;发表在Mlsys Introduction 优化KV cache的策略&#xff0c;主要是集中在系统级别的优化上&#xff0c;比如FlashAttention、PagedAttention&#xff0c;它…

Win11安装安卓子系统WSA

文章目录 简介一、启用Hyper-V二、安装WSA三、安装APKAPK商店参考文献 简介 WSA&#xff1a;Windows Subsystem For Android 一、启用Hyper-V 控制面板 → 程序和功能 → 启用或关闭 Windows 功能 → 勾选 Hyper-V 二、安装WSA 进入 Microsoft Store&#xff0c;下拉框改为 …

PHP排序算法:数组内有A~E,A移到C或者C移到B后排序,还按原顺序排序,循环

效果 PHP代码 public function demo($params){function moveNext($arr){$length count($arr);$lastElement $arr[$length - 1];for ($i $length - 1; $i > 0; $i--) {$arr[$i] $arr[$i - 1];}$arr[0] $lastElement;return $arr;}function moveAndReplace($array, $from…

【数字花园】个人知识库网站搭建:①netlify免费搭建数字花园

目录 [[数字花园]]的构建原理包括三个步骤&#xff1a;五个部署方案教程相关教程使用的平台 步骤信息管理 这里记录的自己搭建数字花园&#xff08;在线个人知识库&#xff09;的经历&#xff0c;首先尝试的是网上普遍使用的方法&#xff0c;也就是本篇文章介绍的。 后面会继续…

el-table表格嵌套子表格:展开所有内容;对当前展开行内容修改,当前行默认展开;

原文1 原文2 原文3 一、如果全部展开 default-expand-all"true" 二、设置有数据的行打开下拉 1、父table需要绑定两个属性expand-row-key和row-key <el-table:data"tableData":expand-row-keys"expends" //expends是数组&#xff0c;设置…

区间预测 | MATLAB实现QRDNN深度神经网络分位数回归时间序列区间预测

区间预测 | MATLAB实现QRDNN深度神经网络分位数回归时间序列区间预测 目录 区间预测 | MATLAB实现QRDNN深度神经网络分位数回归时间序列区间预测效果一览基本介绍模型描述程序设计参考资料 效果一览 基本介绍 MATLAB实现QRDNN深度神经网络分位数回归时间序列区间预测。QRDNN模型…

用.Net Core框架创建一个Web API接口服务器

我们选择一个Web Api类型的项目创建一个解决方案为解决方案取一个名称我们这里选择的是。Net 8.0框架 注意&#xff0c;需要勾选的项。 我们找到appsetting.json配置文件 appsettings.json配置文件内容如下 {"Logging": {"LogLevel": {"Default&quo…