业务设计——用户敏感信息展示脱敏及其反脱敏

业务需求

将用户敏感信息脱敏展示到前端是出于保护用户隐私和信息安全的考虑。

        敏感信息包括但不限于手机号码、身份证号、银行卡号等,这些信息泄露可能导致用户个人信息的滥用、身份盗用等严重问题。脱敏是一种常用的保护用户隐私的方式,它的目的是减少潜在的风险,同时保持一定的用户信息可读性。

比如咱们在选择用户信息以及展示选座信息时,用户证件号码的脱敏展示。

常用脱敏规则 :替换、重排、加密、截断、掩码

Hutool 工具类实现数据脱敏

Hutool包含的组件

Hutool官方文档icon-default.png?t=N7T8https://www.hutool.cn/docs/#/core/%E5%B7%A5%E5%85%B7%E7%B1%BB/%E4%BF%A1%E6%81%AF%E8%84%B1%E6%95%8F%E5%B7%A5%E5%85%B7-DesensitizedUtil

<dependency>    <groupId>cn.hutool</groupId>   <artifactId>hutool-all</artifactId>    <version>5.8.16</version>
</dependency>注意 :Hutool 5.x支持JDK8+, 如果你的项目使用JDK7,请使用
Hutool 4.x版本。本文使用的数据脱敏工具类只有在5.6+版本以上才提供。

       Hutool作为一个Java基础工具类,对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种Util工具类,同时提供以下组件:        

可以根据需求对每个模块单独引入,也可以通过引入hutool-all方式引入所有模块,本文所使用的数据脱敏工具就是在hutool.core模块。

Hutool支持的脱敏数据类型 

Hutool针对数据脱敏业务为不同的敏感数据提供了相应的API来实现脱敏操作,现阶段最新版本的Hutool支持的脱敏数据类型如下,基本覆盖了常见的敏感信息。

  1. 用户id
  2. 中文姓名
  3. 身份证号
  4. 座机号
  5. 手机号
  6. 地址
  7. 电子邮件
  8. 密码
  9. 中国大陆车牌,包含普通车辆、新能源车辆
  10. 银行卡

Hutool提供的脱敏方法如下图所示:

注意 :Hutool 脱敏是通过 * 来代替敏感信息的,具体实现是在StrUtil.hide( )方法中,如果我们想要自定义隐藏符号,则可以把Hutool的源码拷出来,重新实现即可。 

API演示:

    /*** 【手机号码】前三位,后4位,其他隐藏,比如135****2210** @param num 移动电话;* @return 脱敏后的移动电话;*/public static String mobilePhone(String num) {if (StrUtil.isBlank(num)) {return StrUtil.EMPTY;}return StrUtil.hide(num, 3, num.length() - 4);}/*** 【地址】只显示到地区,不显示详细地址,比如:北京市海淀区****** @param address       家庭住址* @param sensitiveSize 敏感信息长度* @return 脱敏后的家庭地址*/public static String address(String address, int sensitiveSize) {if (StrUtil.isBlank(address)) {return StrUtil.EMPTY;}int length = address.length();return StrUtil.hide(address, length - sensitiveSize, length);}/*** 【密码】密码的全部字符都用*代替,比如:******** @param password 密码* @return 脱敏后的密码*/public static String password(String password) {if (StrUtil.isBlank(password)) {return StrUtil.EMPTY;}return StrUtil.repeat('*', password.length());}

搭建Jackson序列化体系

        现在有了数据脱敏工具类,如果前端需要显示数据数据的地方比较多,我们不可能在每个地方都调用一个工具类,这样就显得代码太冗余了,那我们如何通过注解的方式优雅的完成数据脱敏呢?

实现思路

        在 SpringMVC 返回数据时,通过默认的 Jackson 序列化器进行指定,替换为咱们已经包装后的序列化器,这样就能依赖现有解决方案,降低技术复杂度。

代码实现

        定义手机号和证件号的 Jackson 自定义序列化器,并在对应需要脱敏的敏感字段上指定自定义序列化器。

1)身份证号序列化器。

/*** 身份证号脱敏反序列化** @公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料*/
public class IdCardDesensitizationSerializer extends JsonSerializer<String> {@Overridepublic void serialize(String idCard, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {String phoneDesensitization = DesensitizedUtil.idCardNum(idCard, 4, 4);jsonGenerator.writeString(phoneDesensitization);}
}

2)手机号序列化器。

/*** 手机号脱敏反序列化** @公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料*/
public class PhoneDesensitizationSerializer extends JsonSerializer<String> {@Overridepublic void serialize(String phone, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {String phoneDesensitization = DesensitizedUtil.mobilePhone(phone);jsonGenerator.writeString(phoneDesensitization);}
}

3)敏感字段上自定义序列化器。

/*** 乘车人返回参数** @公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料*/
@Data
@Accessors(chain = true)
public class PassengerRespDTO {/*** 证件号码*/@JsonSerialize(using = IdCardDesensitizationSerializer.class)private String idCard;/*** 手机号*/@JsonSerialize(using = PhoneDesensitizationSerializer.class)private String phone;
}

完成上述步骤后,前端调用 HTTP 请求获取数据时,SpringMVC 通过 Jackson 进行序列化数据时,操作证件号码和手机号两个字段就会采用咱们自定义的序列化器,完成敏感信息脱敏功能。


脱敏数据反脱敏

        对接前端的敏感数据脱敏展示功能做到上面这些就已经实现了。但是总感觉哪里不对,因为咱们在购票服务中,下单接口会调用乘车人详细信息接口获取到手机号、证件号等信息保存入库。

        如果我在后端服务里去调用乘车人的信息接口,那岂不是也是脱敏的?这样的话,存储到数据库的数据就不准确了,期望是真实的数据,但是实际是脱敏后的。为此,我们需要想办法把自己脱敏后的数据还原回来,这里介绍几种思路:

Redis缓存原始数据

        将脱敏后的数据和一个随机id一起封装为个对象一起传给前端,我在redis中以这个id为key,未脱敏值为value,当前端需要基于脱敏数据进行相关操作就传个id过来让我后端在redis找到该数据的原始态

        这种方案比较适用于脱敏数据较少的情况,一般对于这种敏感数据展示的需求是比较少的,但是为了实现这么个反脱敏的操作我得浪费一大块缓存取时刻保持一份热点也许相对较小的数据,一个项目的用户量上来了,他们的手机号、身份证号等等敏感数据越来越多,那这样子缓存的占比也越来越大。

对称算法加解密

        这种模式的脱敏就不是运用我们前面提到的替换操作,而是一种对称加解密的过程,将敏感数据采用一个对称算法加密后传输给前端,前端将其传入到后端后再凭借对称解密的方式还原原始数据。

        这种方式优点在于对称加密算法可以提供较高的安全性,只有持有密钥的人才能解密敏感数据,降低了数据泄露的风险。并且对称加解密算法通常具有较高的执行效率,可以快速地对数据进行加解密操作。但是缺点也很明显,由于对称加解密方式是全盘加密和解密,无法对敏感数据进行细粒度的控制,比如只加密部分字段或片段。并且有被拦截通过一些工具进行解码风险,从而泄露数据。


总结

        本文主要介绍了数据脱敏的相关内容,首先介绍了数据脱敏的概念,在此基础上介绍了常用的数据脱敏规则;随后介绍了本文的重点Hutool工具及其使用方法,在此基础上进行了实操,分别演示了使用DesensitizedUtil工具类、配合Jackson通过注解的方式完成数据脱敏;最后,介绍了一些常见的数据反脱敏方法,本文内容如有不当之处,还请大家批评指正。

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

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

相关文章

IOC课程整理-6 Spring IoC 依赖注入

1 依赖注入的模式和类型 模式 类型 2 自动绑定&#xff08;Autowiring&#xff09; 官方定义 “自动装配是Spring框架中一种机制&#xff0c;用于自动解析和满足bean之间的依赖关系。通过自动装配&#xff0c;Spring容器可以根据类型、名称或其他属性来自动连接协作的bean&…

LeetCode 541 反转字符串 II 简单

题目 - 点击直达 1. 541 反转字符串 II 简单1. 题目详情1. 原题链接2. 题目要求3. 基础框架 2. 解题思路1. 思路分析2. 时间复杂度3. 代码实现 1. 541 反转字符串 II 简单 1. 题目详情 给定一个字符串 s 和一个整数 k&#xff0c;从字符串开头算起&#xff0c;每计数至 2k 个…

OpenCV官方教程中文版 —— 模板匹配

OpenCV官方教程中文版 —— 模板匹配 前言一、原理二、OpenCV 中的模板匹配三、多对象的模板匹配 前言 在本节我们要学习&#xff1a; 使用模板匹配在一幅图像中查找目标 函数&#xff1a;cv2.matchTemplate()&#xff0c;cv2.minMaxLoc() 一、原理 模板匹配是用来在一副大…

BUUCTF Reverse 新年快乐

下载文件先查壳&#xff0c;可以看到有UPX壳 用upx脱壳 拖到ida pro32&#xff0c;shiftF12查看字符串&#xff0c;看到关键字flag&#xff0c;双击进去 双击然后f5查看伪代码 main函数伪代码 关键函数&#xff1a; strncmp(const char *str1, const char *str2, size_t n)…

Epinoia-有状态网络的意图验证模块,略读

Epinoia relies on a unified model for NFs by leveraging the causal precedence relationshipsthat exist between NF packet I/Os and states. 这句话的意思是&#xff1a;“Epinoia依靠一种统一的网络功能&#xff08;NF&#xff09;模型&#xff0c;通过利用存在于 NF 包…

群智能算法之模拟退火算法

1.模拟退火算法简介&#xff1a; 2.模拟退火算法的关键点&#xff1a; &#xff08;1&#xff09;随机的更新可行解x,判断可行解x对应的函数值和原来函数值之间的大小&#xff1a;如果优于原来的函数值&#xff0c;则让新的可行解x为问题的解&#xff1b;否则以一定的概率(大于…

FL Studio21.2.0.3421最新汉化破解版中文解锁下载完整版本

音乐在人们心中的地位日益增高&#xff0c;近几年音乐选秀的节目更是层出不穷&#xff0c;喜爱音乐&#xff0c;创作音乐的朋友们也是越来越多&#xff0c;音乐的类型有很多&#xff0c;好比古典&#xff0c;流行&#xff0c;摇滚等等。对新手友好程度基本上在首位&#xff0c;…

【存储】lotusdb的原理及实现

最近看了lotusdb的源码。lotusdb是一个golang实现的嵌入式的持久化kv存储。 从整体设计上看&#xff0c;lotusdb采用了类似LSM树的架构&#xff0c;并采用了针对SSD的优化&#xff0c;将key和value分开存储。在此基础上&#xff0c;lotusdb将LSM树中存储key的SST使用B树或者ha…

WORD中的表格内容回车行距过大无法调整行距

word插入表格&#xff0c;编辑内容&#xff0c;换行遇到如下问题&#xff1a; 回车后行距过大&#xff0c;无法调整行距。 解决方法&#xff08;并行&#xff09;&#xff1a; 方法1&#xff1a;选中要调整的内容&#xff0c;菜单路径&#xff1a;“编辑-清除-格式” 方法2&am…

银河麒麟服务器版v4安装程序缺少依赖包,改为利用手机联网在线安装

1 将安卓手机连接使用usb转typec线连接到服务器的usb口。&#xff08;linux桌面版&#xff09;也可以类似的方法手机联网。 2 在手机热点中打开usb共享 3 使用ifconfig命令找到手机被服务器识别成的网卡名 4 使用dhclient “手机网卡名”命令&#xff0c;使服务器能上网。 5 变…

No173.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

Java SE 学习笔记(十八)—— 注解、动态代理

目录 1 注解1.1 注解概述1.2 自定义注解1.3 元注解1.4 注解解析1.5 注解应用于 junit 框架 2 动态代理2.1 问题引入2.2 动态代理实现 1 注解 1.1 注解概述 Java 注解&#xff08;Annotation&#xff09;又称Java标注&#xff0c;是JDK 5.0引入的一种注释机制&#xff0c;Java语…

Unity ScrollView最底展示

Unity ScrollView最底展示 问题方案逻辑 问题 比如在做聊天界面的时候我们肯定会使用到ScrollView来进行展示我们的聊天内容&#xff0c;那么这个时候来新消息的时候就需要最底展示&#xff0c;我认为这里有两种方案&#xff1b; 一种是通过算法每一条预制体的高度*一共多少…

NPMCM历年赛题汇总

题目来源:全国研究生数学建模大赛 2021–2023年 年份题号题目2022A移动场景超分辨定位问题2022B方形件组批优化问题2022C汽车制造涂装–总装缓存调序区调度优化问题2022DPIAS架构芯片资源排布问题2022E草原放牧策略问题2022FCOVID-19疫情期间生活物资的科学管理问题2021A相关…

Docker中Failed to initialize NVML: Unknown Error

参考资料 Docker 中无法使用 GPU 时该怎么办&#xff08;无法初始化 NVML&#xff1a;未知错误&#xff09; SOLVED Docker with GPU: “Failed to initialize NVML: Unknown Error” 解决方案需要的条件: 需要在服务器上docker的admin list之中. 不需要服务器整体的admin权限.…

驼峰命名法

文章目录 前言&#xff08;一&#xff09;大驼峰&#xff08;二&#xff09;小驼峰 前言 驼峰命名法 增加代码的可读性 &#xff08;一&#xff09;大驼峰 命名 类 所有单词的首字母都要大写 &#xff08;二&#xff09;小驼峰 命名 变量名 和 方法名 如果有一个单词&#…

汇编运算符和表达式

运算符&#xff1a; 汇编语言由表达式和运算符组成&#xff0c;运算符分为数值运算符和属性运算符。属性运算符面向变量或标号。 数值运算符&#xff1a; 算术运算符&#xff1a; 运算符类型 ✓ ( 正号 ) 、 -( 负号 ) ✓ ( 加 ) 、 -( 减 ) 、 *( 乘 ) 、 /( 除 ) 、 MO…

Linux下的IMX6ULL——开发板的第一个APP和驱动实验(三)

前言&#xff1a; 万事开头难&#xff0c;如果我们在开发板上开发出第一个应用程序&#xff0c;第一个驱动程序&#xff0c;那么后续的开发就会稍微简单点&#xff0c;下面让我们来进行第一个应用程序和第一驱动程序的开发吧。 目录 一、开发板的第1个APP实验 1.通过Git仓库…

批量去除pdf每一页相同未知的同样的内容

例如我想去除每一页右下角的www.alevelcollege.com ①打开acrobat pro ②编辑文件和图像 ③ctrlF输入字符串www.alevelcollege.com替换为空 ④鼠标点击替换 ⑤回车键按下不放&#xff0c;会自动翻页&#xff0c;直到翻页到最后一页。

算法训练|数据流中的中位数

LCR 160. 数据流中的中位数 - 力扣&#xff08;LeetCode&#xff09; 总结&#xff1a;这题自己最开始的想法是直接使用vector容器&#xff0c;每次取中位数的时候就进行一次排序&#xff0c;超时。题解很巧妙的利用大根堆和小根堆来解决问题&#xff0c;大根堆和小根堆各存一…