注解实现json序列化的时候自动进行数据脱敏
最近在进行开发的时候遇到一个问题,需要对用户信息进行脱敏处理,原有的方式是写一个util类,在需要脱敏的字段查出数据后,显示掉用方法处理后再set回去,觉得这种方式能实现功能,但是不是特别优雅,想找个比较优雅的实现 思考了一下,觉得数据只有在输出的时候进行脱敏处理即可,其它都是在内存阶段,相对来说都是比较安全的,输出阶段我想到了json序列化,因为我们用的restful接口输出json,于是去查询了一下相关的资源,jackson可以指定某个字段的自定义序列化类,那么还有一个问题,我指定了用某个类进行序列化,但是在序列化的时候如果判断脱敏的类型呢,翻看网上大神的文章得知,ContextualSerializer是 Jackson 提供的另一个序列化相关的接口,它的作用是通过字段已知的上下文信息定制JsonSerializer,只需要实现createContextual方法即可。废话少说,下面上代码:
用户信息实体:
@Data
public class UserDetailResponse {private Long useId;@ApiModelProperty(value = "用户编号")private String useNo;@ApiModelProperty(value = "用户姓名")private String useName;@SensitiveInfo(SensitiveType.MOBILE_PHONE)@ApiModelProperty(value = "用户手机号")private String mobile;@ApiModelProperty(value = "用户性别")private String sex;@ApiModelProperty(value = "用户年龄")private int age;@ApiModelProperty(value = "用户籍贯")private String nativePlace;@SensitiveInfo(SensitiveType.ID_CARD)@ApiModelProperty(value = "用户身份证号")private String idCard;@ApiModelProperty(value = "用户身份证号")private String borrowingLevel;
}
脱敏类型枚举类
public enum SensitiveType {/*** 中文名*/CHINESE_NAME,/*** 身份证号*/ID_CARD,/*** 座机号*/FIXED_PHONE,/*** 手机号*/MOBILE_PHONE,/*** 地址*/ADDRESS,/*** 电子邮件*/EMAIL,/*** 银行卡*/BANK_CARD,/*** 公司开户银行联号*/CNAPS_CODE
}
脱敏注解类
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveInfoSerialize.class)
public @interface SensitiveInfo {public SensitiveType value();
}
脱敏序列化类
public class SensitiveInfoSerialize extends JsonSerializer<String> implementsContextualSerializer {private SensitiveType type;public SensitiveInfoSerialize() {}public SensitiveInfoSerialize(final SensitiveType type) {this.type = type;}@Overridepublic void serialize(final String s, final JsonGenerator jsonGenerator,final SerializerProvider serializerProvider) throws IOException, JsonProcessingException {switch (this.type) {case CHINESE_NAME: {jsonGenerator.writeString(SensitiveInfoUtils.chineseName(s));break;}case ID_CARD: {jsonGenerator.writeString(SensitiveInfoUtils.idCardNum(s));break;}case FIXED_PHONE: {jsonGenerator.writeString(SensitiveInfoUtils.fixedPhone(s));break;}case MOBILE_PHONE: {jsonGenerator.writeString(SensitiveInfoUtils.mobilePhone(s));break;}case ADDRESS: {jsonGenerator.writeString(SensitiveInfoUtils.address(s, 4));break;}case EMAIL: {jsonGenerator.writeString(SensitiveInfoUtils.email(s));break;}case BANK_CARD: {jsonGenerator.writeString(SensitiveInfoUtils.bankCard(s));break;}case CNAPS_CODE: {jsonGenerator.writeString(SensitiveInfoUtils.cnapsCode(s));break;}}}@Overridepublic JsonSerializer<?> createContextual(final SerializerProvider serializerProvider,final BeanProperty beanProperty) throws JsonMappingException {if (beanProperty != null) { // 为空直接跳过if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) { // 非 String 类直接跳过SensitiveInfo sensitiveInfo = beanProperty.getAnnotation(SensitiveInfo.class);if (sensitiveInfo == null) {sensitiveInfo = beanProperty.getContextAnnotation(SensitiveInfo.class);}if (sensitiveInfo != null) { // 如果能得到注解,就将注解的 value 传入 SensitiveInfoSerializereturn new SensitiveInfoSerialize(sensitiveInfo.value());}}return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);}return serializerProvider.findNullValueSerializer(beanProperty);}
}
脱敏处理util类
public class SensitiveInfoUtils {/*** [中文姓名] 只显示第一个汉字,其他隐藏为2个星号<例子:李**>*/public static String chineseName(final String fullName) {if (StringUtils.isBlank(fullName)) {return "";}final String name = StringUtils.left(fullName, 1);return StringUtils.rightPad(name, StringUtils.length(fullName), "*");}/*** [中文姓名] 只显示第一个汉字,其他隐藏为2个星号<例子:李**>*/public static String chineseName(final String familyName, final String givenName) {if (StringUtils.isBlank(familyName) || StringUtils.isBlank(givenName)) {return "";}return chineseName(familyName + givenName);}/*** [身份证号] 显示最后四位,其他隐藏。共计18位或者15位。<例子:*************5762>*/public static String idCardNum(final String id) {if (StringUtils.isBlank(id)) {return "";}return StringUtils.left(id, 3).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(id, 3), StringUtils.length(id), "*"),"***"));}/*** [固定电话] 后四位,其他隐藏<例子:****1234>*/public static String fixedPhone(final String num) {if (StringUtils.isBlank(num)) {return "";}return StringUtils.leftPad(StringUtils.right(num, 4), StringUtils.length(num), "*");}/*** [手机号码] 前三位,后四位,其他隐藏<例子:138******1234>*/public static String mobilePhone(final String num) {if (StringUtils.isBlank(num)) {return "";}return StringUtils.left(num, 2).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(num, 2), StringUtils.length(num), "*"),"***"));}/*** [地址] 只显示到地区,不显示详细地址;我们要对个人信息增强保护<例子:北京市海淀区****>** @param sensitiveSize 敏感信息长度*/public static String address(final String address, final int sensitiveSize) {if (StringUtils.isBlank(address)) {return "";}final int length = StringUtils.length(address);return StringUtils.rightPad(StringUtils.left(address, length - sensitiveSize), length, "*");}/*** [电子邮箱] 邮箱前缀仅显示第一个字母,前缀其他隐藏,用星号代替,@及后面的地址显示<例子:g**@163.com>*/public static String email(final String email) {if (StringUtils.isBlank(email)) {return "";}final int index = StringUtils.indexOf(email, "@");if (index <= 1) {return email;} else {return StringUtils.rightPad(StringUtils.left(email, 1), index, "*").concat(StringUtils.mid(email, index, StringUtils.length(email)));}}/*** [银行卡号] 前六位,后四位,其他用星号隐藏每位1个星号<例子:6222600**********1234>*/public static String bankCard(final String cardNum) {if (StringUtils.isBlank(cardNum)) {return "";}return StringUtils.left(cardNum, 6).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(cardNum, 4), StringUtils.length(cardNum), "*"),"******"));}/*** [公司开户银行联号] 公司开户银行联行号,显示前两位,其他用星号隐藏,每位1个星号<例子:12********>*/public static String cnapsCode(final String code) {if (StringUtils.isBlank(code)) {return "";}return StringUtils.rightPad(StringUtils.left(code, 2), StringUtils.length(code), "*");}}
效果图:
此文主要参考了下面几位大神的文章
http://www.scienjus.com/get-field-annotation-property-by-jackson-contextualserializer/
http://blog.csdn.net/liuc0317/article/details/48787793
http://www.voidcn.com/article/p-ezjgnfeh-bee.html
相关文章:
注解实现json序列化的时候自动进行数据脱敏
最近在进行开发的时候遇到一个问题,需要对用户信息进行脱敏处理,原有的方式是写一个util类,在需要脱敏的字段查出数据后,显示掉用方法处理后再set回去,觉得这种方式能实现功能,但是不是特别优雅,…...
使用Python下载文件的简易指南
在日常的数据处理、自动化任务或软件开发中,经常需要从网络上下载文件。Python作为一门功能强大的编程语言,提供了多种方法来实现文件的下载。本文将介绍几种常用的方法来使用Python下载文件,包括使用requests库和urllib库。 准备工作 在开…...
中秋国庆双节长假,景区迎来客流高峰,如何保障景区安全管理?
一、方案背景 近年来,国内旅游市场持续升温,节假日期间景区游客数量激增,给景区安全管理带来了巨大挑战。然而,景区安全风险意识不足、防护措施不完善、游客安全意识欠缺等问题依然存在,导致景区安全事故频发。随着中秋…...
多维数组转一维数组:探索 JavaScript 中的数组扁平化
在 JavaScript 编程中,我们经常会遇到需要将多维数组转换为一维数组的情况。无论是处理复杂的数据结构还是进行数据的进一步操作,数组扁平化都是一个常见且有用的技术。本文将介绍几种在 JavaScript 中将多维数组转换为一维数组的方法。 什么是数组扁平…...
配环境时的一些记录
连centos:正常连就好(密码验证码)连rocky:需要在centos上连,终端里直接ssh [rocky_ip];在vscode中需要: 修改配置文件:打开命令面板(ctrlshiftp) -> 输入并…...
如何解析域名到网站?
在现代互联网中,域名解析是用户访问网站的关键过程。用户通过输入易于记忆的域名来访问网站,而背后则是复杂的域名解析机制将域名转换为服务器的IP地址,使得浏览器能够找到并加载目标网站。聚名网详细介绍域名解析的过程及其相关技术。 一、…...
【F172】基于Springboot+vue实现的智能菜谱系统
作者主页:Java码库 主营内容:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 项目描述 近些年,随着中国经济发展,人民的…...
Spring-AOP核心源码、原理详解前篇
本文主要分4部分 Aop原理介绍介绍aop相关的一些类通过源码详解aop代理的创建过程通过源码详解aop代理的调用过程Aop代理一些特性的使用案例 Spring AOP原理 原理比较简单,主要就是使用jdk动态代理和cglib代理来创建代理对象,通过代理对象来访问目标对象…...
Reflection反射——Class类
概述 在Java中,除了int等基本类型外,Java的其他类型全部都是class(包括interface)。例如: String、Object、Runnable、Exception…… Java反射机制是Java语言的一个重要特性。在学习Java反射机制前,需要了…...
王朝兴替的因果
天道好轮 回,苍天饶过谁。王朝兴亡,天道无情。 而其因果循环,天道之森严,让人敬畏。 王朝创业帝王造下什么业,后世子孙在兴替之时,往往要承担何种果 报。 中国几千年的王朝史,因 果循环&…...
损坏SD数据恢复的8种有效方法
SD卡被用于许多不同的产品来存储重要数据,如图片和重要的商业文件。如果您的SD卡坏了,您需要SD数据恢复来获取您的信息。通过从损坏的SD卡中取回数据,您可以确保重要文件不会永远丢失,这对于工作或个人原因是非常重要的。 有许多…...
好评如潮的年度黑马韩剧,惊喜从一上线就开始
韩剧一直以来都以细腻的情感和紧凑的剧情打动观众,而最近播出的一部作品更是掀起了不小的风波-《法官大人》。孙贤周与金明民两大演技派领衔主演,凭借他们的深沉演技和复杂的角色关系,让这部剧集迅速成为热议焦点。故事围绕着一起交通事故展开…...
超好用的PC端语音转文字工具CapsWriter-Offline结合内网穿透实现远程使用
文章目录 前言1. 软件与模型下载2. 本地使用测试3. 异地远程使用3.1 内网穿透工具下载安装3.2 配置公网地址3.3 修改config文件3.4 异地远程访问服务端 4. 配置固定公网地址4.1 修改config文件 5. 固定tcp公网地址远程访问服务端 前言 本文主要介绍如何在Windows系统电脑端使用…...
1、https的全过程
目录 一、概述二、SSL过程如何获取会话秘钥1、首先认识几个概念:2、没有CA机构的SSL过程:3、没有CA机构下的安全问题4、有CA机构下的SSL过程 一、概述 https是非对称加密和对称加密的过程,首先建立https链接需要经过两轮握手: T…...
抢鲜体验 PolarDB PG 15 开源版
unsetunsetPolarDB 商业版unsetunset 8 月,PolarDB PostgreSQL 版兼容 PostgreSQL 15 版本(商业版)正式发布上线。 当前版本主要增强优化了以下方面: 改进排序功能:改进内存和磁盘排序算法。 增强SQL功能:支…...
UEFI——使用标准C库
一、C标准库 C标准库是ANSL C标准为C语言定义的标准库。C标准库包含15个头文件:assert.h ctype.h error.h float.h limits.h locale.h math.h setjmp.h signal.h stdarg.h stddef.h stdio.h stdlib.h string.h time.h。标准库函数与C语言的紧密结合给我们开发程序带…...
[全网首发]怎么让国行版iPhone使用苹果Apple Intelligence
全文共分为两个部分:第一让苹果手机接入AI,第二是让苹果手机接入ChatGPT 4o功能。 一、国行版iPhone开通 Apple Intelligence教程 打破限制:让国行版苹果手机也能接入AI 此次发布会上,虽然国行 iPhone16 系列不支持 GPT-4o&…...
C语言-综合案例:通讯录
传送门:C语言-第九章-加餐:文件位置指示器与二进制读写 目录 第一节:思路整理 第二节:代码编写 2-1.通讯录初始化 2-2.功能选择 2-3.增加 和 扩容 2-4.查看 2-5.查找 2-6.删除 2-7.修改 2-8.退出 第三节:测试 下期…...
XWiki中添加 html 二次编辑失效
如果直接在 XWiki 中添加 html, 例如 修改颜色, 新窗口打开主页面等功能, 首次保存是生效的. 如果再次编辑, 则失效, 原因是被转换成了 Markdown 的代码, 而 Markdown 不支持. 解决这个问题可以使用 HTML 宏. 在 XWiki 中使用 Markdown 1.2 语法时,默认 Markdown …...
外贸|基于Java+vue的智慧外贸平台系统(源码+数据库+文档)
外贸|智慧外贸平台|外贸服务系统 目录 基于Javavue的智慧外贸平台系统 一、前言 二、系统设计 三、系统功能设计 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍:✌️大厂码农|毕设布道师&…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
