springboot实现数据脱敏
springboot实现数据脱敏
-
怎么说呢,写着写着发觉 ”这写的什么玩意“ 。
总的来说就是,这篇文章并不能解决数据脱敏问题,但以下链接可以。
SpringBoot中利用自定义注解优雅地实现隐私数据脱敏
然后回到本文,本来是想基于AOP代理,实现返回数据脱敏的,具体流程是:
-
在controller做切面,实现返回通知
-
返回通知中获取返回值对象
-
利用反射获取返回值字段
-
标有脱敏注释的字段做脱敏处理
说着好像一套一套的,但事实上,忽略了一个重要的问题,复杂对象很难做反射,例如集合List,Set,Map,或者对象的引用也是对象,就算用多重判断深度遍历,但是反射带来的耗时以及空间开销都是值得思考的,总而言之,这是一个很low的方案。
但是我很少用到反射,并且感觉既然都写到这了,不如记录一下,aop和反射结合,以后可能会用来实现其他有趣的功能也说不定。那就记录一下吧。
-
1. 引入依赖
<!-- 引入aop支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
2. 实现两个注解
一个标注在controller方法上,Service也可以
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DesensitizeResult {}
一个标注在属性上
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DesensitizeField {// 字段名称,给字段起个名字而已,没啥用String name() default "字段名";// 前面正常显示字符长度(不脱敏长度)int prefixShow() default 1;// 后面正常显示字符长度(不脱敏)长度int suffixShow() default 0;// 脱敏引用符号String symbol() default "*";
}
3. 编写切面方法类
@Aspect
@Component
public class DesensitizeAspect {@Pointcut("@annotation(com.example.testdemo.annotation.DesensitizeResult)")public void getDesensitizeAnno(){}/*** 返回贴面编程,对返回结果result做脱敏操作* @param joinPoint 切点* @param result 目标方法返回结果*/@AfterReturning(pointcut = "getDesensitizeAnno()",returning = "result")public void afterReturn(JoinPoint joinPoint,Object result){// 获取返回结果类的所有属性数组Class resultClass = result.getClass();Field[] declaredFields = resultClass.getDeclaredFields();for (Field field : declaredFields){// 循环判断属性中是否存在自定义脱敏注解@DesensitizeFieldfor (Annotation annotation : field.getAnnotations()) {Class<? extends Annotation> aClass = annotation.annotationType();if (aClass.equals(DesensitizeField.class)){DesensitizeField desensitizeField = (DesensitizeField) annotation;// 对标有@DesensitizeField的属性进行脱敏处理field.setAccessible(true); // 先将该属性改为允许值修改try {String originStr = (String)field.get(result); // 获取原来的值// 字符串脱敏String desensitizeValue = this.desensitizeStr(originStr, desensitizeField.prefixShow(),desensitizeField.suffixShow(), desensitizeField.symbol());field.set(result,desensitizeValue); // 将脱敏后的字符串写入} catch (IllegalAccessException e) {throw new RuntimeException(e);}}}}}/*** * @param originStr 原字符串* @param prefixShow 前置正常字符串长度* @param suffixShow 后置正常字符串长度* @param symbol 脱敏字符显示标志* @return 脱敏后字符串*/private String desensitizeStr(String originStr, int prefixShow, int suffixShow, String symbol){int length = originStr.length();// 避免out of indexprefixShow = Math.min(prefixShow, length);suffixShow = Math.min(suffixShow,length);// 前后显示数据超过数据是指长度处理,OutOfRange处理if (prefixShow+suffixShow>length){prefixShow=length;suffixShow=0;}String desensitizeValue = originStr.substring(0,prefixShow)+symbol.repeat(length-prefixShow-suffixShow)+originStr.substring(length-suffixShow);return desensitizeValue;}}
如上代码所示,只是针对单个简单对象做字段脱敏,复杂对象就完了
4. 测试实体类
@Data
@ToString
public class UserInfo {private String id;private String account;private String nickname;@DesensitizeField(name = "真实姓名",prefixShow = 1)private String realName;@DesensitizeField(name = "密码",prefixShow = 0)private String password;@DesensitizeField(name = "手机号",prefixShow = 3,suffixShow = 1)private String mobile;@DesensitizeField(name = "身份证号",prefixShow = 3)private String identityId;private String createTime;}
5. 测试接口
@RestController
public class TestController {@DesensitizeResult // aop切面脱敏数据@GetMapping("/userInfo")public UserInfo getUserInfo(){UserInfo userInfo = new UserInfo();userInfo.setId("123456");userInfo.setAccount("abcdef");userInfo.setMobile("13579246810");userInfo.setNickname("BigBoss");userInfo.setRealName("张小凡");userInfo.setIdentityId("430121200001011321");userInfo.setPassword("Mm123456#");return userInfo;}
}
6.测试

至此,全文完毕,另外盘算着下次把上面链接的方案偷过来再发一篇。
相关文章:
springboot实现数据脱敏
springboot实现数据脱敏 怎么说呢,写着写着发觉 ”这写的什么玩意“ 。 总的来说就是,这篇文章并不能解决数据脱敏问题,但以下链接可以。 SpringBoot中利用自定义注解优雅地实现隐私数据脱敏 然后回到本文,本来是想基于AOP代理&am…...
uniapp实现多时间段设置
功能说明: 1 点击新增时间,出现一个默认时间段模板,不能提交 2 点击“新增时间文本”,弹出弹窗,选择时间,不允许开始时间和结束时间同时为00:00, <view class"item_cont"> …...
uni-app - 去除隐藏页面右侧垂直滚动条
全局配置 "globalStyle": { //全局配置 "scrollIndicator":"none", // 不显示滚动条 "app-plus":{ "scrollIndicator":"none" // 在APP平台都不显示滚动条 } }局部配置 "path": "pages/ind…...
一次简单的 Http 请求异常处理 (请求的 url 太长, Nginx 直接返回 400, 导致请求服务异常)
1 结论 按照惯例直接说结论。 后台服务 A 有一个 Http 接口, 代码如下: RequestMapping(value "/user", method RequestMethod.GET) public List<UserInfoVo> getUserInfoByUserIds(RequestParam(value "userIds") List<String> userIds…...
spring Cloud在代码中如何应用,erueka 客户端配置 和 服务端配置,Feign 和 Hystrix做高可用配置
文章目录 Eureka一、erueka 客户端配置二、eureka 服务端配置 三、高可用配置FeignHystrix 通过这篇文章来看看spring Cloud在代码中的具体应用,以及配置和注解; Eureka 一、erueka 客户端配置 1、Eureka 启禁用 eureka.client.enabledtrue 2、Eurek…...
C#8.0中新语法“is {}“的介绍及使用
一、C#7.0及之前is的使用 is操作符检查表达式的结果是否与给定类型兼容,或者(从c# 7.0开始)根据模式测试表达式。有关类型测试is操作符的信息,请参阅类型测试和类型转换操作符文章的is操作符部分。 1、is 模式匹配 从C࿰…...
编译器设计01-入门概述
编译器作用概述 源代码 → 编译器 目标代码 源代码\xrightarrow{\ \ \ 编译器\ \ \ }目标代码 源代码 编译器 目标代码 编译阶段概述 编译处理包括两个阶段:前端处理和后端处理,中间过程生成语法树。 编译处理:源代码 → 语法树 …...
SpringBoot封装Elasticsearch搜索引擎实现全文检索
一、前言 注:本文实现了Java对Elasticseach的分页检索/不分页检索的封装 ES就不用过多介绍了,直接上代码: 二、实现步骤: 创建Store类(与ES字段对应,用于接收ES数据) import com.alibaba.f…...
(C)一些题4
1. 以下叙述中正确的是( )。 A.C程序中的注释只能出现在程序的开始位置和语句的后面 B.C程序书写格式严格,要求行内只能写一个语句 C,C程序书写格式自由,一个语句可以写在多行上 D.用C语言编写的程序只能放在一个程序文件中 2.设有如下程序段 char …...
ChatGPT初体验:注册、API Key获取与ChatAPI调用详解
自从2022年10月,ChatGPT诞生以后,实际上已经改变了很多!其火爆程度简直超乎想象,一周的时间用户过百万,两个月的时间用户过亿。 目前ChatGPT4已经把2023年4月以前的人类的知识都学习到了,在软件工程里面&am…...
TCP/IP协议、三次握手、四次挥手
TCP/IP TCP/IP协议分层TCP头部三次握手TCP四次挥手常见问题1、什么是TCP网络分层2、TCP为什么是三次握手,不是两次或者四次?3、TCP为什么是四次挥手,为什么不能是三次挥手将第二次挥手和第三次挥手合并?4、四次挥手时为什么TIME_W…...
Android U 匹配不到APN,无法发起数据建立的问题分析
问题 打开数据开关后,没有data PDN请求发起,因此无法上网。 根据日志确定是没有找到合适的data profile,原因一般有: 1、APN 没有配置 2、APN 类型/网络能力不满足——APN type或bearer 3、APN 配置了但被disable了——APN p…...
如何打造“面向体验”的音视频能力——对话火山引擎王悦
编者按:随着全行业视频化的演进,我们置身于一个充满创新与变革的时代。在这个数字化的浪潮中,视频已经不再只是传递信息的媒介,更是重塑了我们的交互方式和体验感知。作为字节跳动的“能力溢出”,火山引擎正在飞速奔跑…...
什么是NoOps
过去几年,自动化一直在推动整个 IT 行业向前发展。通过自动化某些任务,开发团队可以提高其能力,而无需感受到雇用新团队成员的预算压力。自动化还保证了更高的效率,特别是在操作和维护方面。 传统的软件开发工作流程涉及开发团队…...
Unity - Graphic解析
Gpahic 的作用 Graphic 是 Unity最基础的图形基类。主要负责UGUI的显示部分。 由上图可以看你出我们经常使用的Image,Text,都是继承自Graphic。 Graphic的渲染流程 在Graphic的源码中有以下属性 [NonSerialized] private CanvasRenderer m_CanvasRend…...
哈希思想的应用
目录 1.位图 位图的实现 题目变形一 题目变形二 题目变形三 总结: 2.布隆过滤器 概念 布隆过滤器的实现 3.哈希切割的思想 1.位图 哈希表和位图是数据结构中常用的两种技术。哈希表是一种数据结构,通过哈希函数把数据和位置进行映射,…...
React入门使用 (官方文档向 Part1)
文章目录 React组件:万物皆组件 JSX: 将标签引入 JavaScriptJSX 规则1. 只能返回一个根元素2. 标签必须闭合3. 使用驼峰式命名法给 ~~所有~~ 大部分属性命名!高级提示:使用 JSX 转化器 在 JSX 中通过大括号使用 JavaScript使用引号传递字符串使用大括号&…...
87基于matlab的双卡尔曼滤波算法
基于matlab的双卡尔曼滤波算法。第一步使用了卡尔曼滤波算法,用电池电压来修正SOC,然后将修正后的SOC作为第二个卡尔曼滤波算法的输入,对安时积分法得到的SOC进行修正,最终得到双卡尔曼滤波算法SOC估计值。结合EKF算法和安时积分法…...
Jacobi迭代与SOR迭代求解希尔伯特矩阵
给出线性方程组 Hn*x b,其中系数矩阵Hn为希尔伯特矩阵: 假设 x ∗ (1, 1, . . . , 1)T,b Hnx ∗。若取 n 6,8, 10,分别用 Jacobi 迭代法及 SOR迭代(ω 1, 1:25,1:5)求解,比较计算结果。…...
【云备份】配置加载文件模块
文章目录 配置信息设计配置文件加载cloud.conf配置文件单例模式的使用ReadConfigFile —— 读取配置文件GetInstance —— 创建对象其他函数的实现 具体实现cloud.confconfig.hpp 配置信息设计 使用文件配置加载一些程序运行的关键信息 可以让程序的运行更加灵活 配置信息&am…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...
字符串哈希+KMP
P10468 兔子与兔子 #include<bits/stdc.h> using namespace std; typedef unsigned long long ull; const int N 1000010; ull a[N], pw[N]; int n; ull gethash(int l, int r){return a[r] - a[l - 1] * pw[r - l 1]; } signed main(){ios::sync_with_stdio(false), …...
PydanticAI快速入门示例
参考链接:https://ai.pydantic.dev/#why-use-pydanticai 示例代码 from pydantic_ai import Agent from pydantic_ai.models.openai import OpenAIModel from pydantic_ai.providers.openai import OpenAIProvider# 配置使用阿里云通义千问模型 model OpenAIMode…...
虚幻基础:角色旋转
能帮到你的话,就给个赞吧 😘 文章目录 移动组件使用控制器所需旋转:组件 使用 控制器旋转将旋转朝向运动:组件 使用 移动方向旋转 控制器旋转和移动旋转 缺点移动旋转:必须移动才能旋转,不移动不旋转控制器…...
