项目开发中用户数据脱敏如何实现?

SQL实现

首先可以采用sql语句的形式:

利用 CONCAT()、LEFT()和RIGHT() 字符串函数组合使用,请看下面具体实现


-- CONCAT(str1,str2,…):返回结果为连接参数产生的字符串
-- LEFT(str,len):返回从字符串str 开始的len 最左字符
-- RIGHT(str,len):从字符串str 开始,返回最右len 字符

 举个栗子:

-- 电话号码脱敏sql:SELECT mobilePhone AS 脱敏前电话号码,CONCAT(LEFT(mobilePhone,3), '********' ) AS 脱敏后电话号码 FROM t_s_user-- 身份证号码脱敏sql:SELECT idcard AS 未脱敏身份证, CONCAT(LEFT(idcard,3), '****' ,RIGHT(idcard,4)) AS 脱敏后身份证号 FROM t_s_user

java实现

通过自定义注解的形式实现

提供两种方式:正则表达式和长度判定形式

举个栗子:对用户姓名进行脱敏

1.定义脱敏名称实体类

/*** 中文名称脱敏**/
public class SensitiveChineseName implements IStrategy {@Overridepublic String desensitization(String source,int begin,int end) {if(begin != SensitiveDefaultLengthEnum.CHINESE_NAME.getBegin() && begin !=0){return SensitiveInfoUtils.chineseName(source,begin);}return SensitiveInfoUtils.chineseName(source, SensitiveDefaultLengthEnum.CHINESE_NAME.getBegin());}}

 2.自定义工具类 实现统一管理进行数据处理


/*** 数据脱敏的工具类**/
public class SensitiveInfoUtils {/*** [中文姓名] 只显示第一(showLength)个汉字,其他隐藏为2个星号<例子:李**>*/public static String chineseName(final String fullName, int showLength) {if (StringUtils.isBlank(fullName)) {return "";}if(StringUtils.length(fullName) <= showLength){return fullName;}final String name = StringUtils.left(fullName, showLength);return StringUtils.rightPad(name, StringUtils.length(fullName), "*");}
}

3.定义枚举类 获取脱敏信息的类型


import lombok.Getter;/*** 枚举默认显示的长度**/
public enum SensitiveDefaultLengthEnum {/*** 默认长度*/DEFAULT(0,0),/***中文姓名*/CHINESE_NAME(1,0),/*** 密码*/PASSWORD(6,0),/*** 身份证号*/ID_CARD_NUM(0,4),/*** 固定电话*/FIXED_PHONE(0,4),/*** 电话*/MOBILE(3,4),/*** 地址*/ADDRESS(6,0),/*** 邮箱*/EMAIL(1,0),/*** 银行卡号*/BANKCARD(6,4),/*** 默认策略*/DEFAULT_STRATEGY(6,0),;SensitiveDefaultLengthEnum(int begin, int end){this.begin = begin;this.end = end;};/*** 开始长度*/@Getterprivate int begin;/*** 结束长度*/@Getterprivate int end;}

 4.自定义注解实现


/*** 序列化实现类**/
@NoArgsConstructor
public class SensitiveInfoSerialize extends JsonSerializer<String> implementsContextualSerializer {/*** 脱敏策略*/private IStrategy strategy;/*** 开始显示的字符长度*/private int begin;/*** 结尾显示的字符长度*/private int end;/*** 脱敏的正则*/private String pattern;/*** 替换后的字符*/private String replaceChar;public SensitiveInfoSerialize(IStrategy strategy, String pattern, String replaceChar,int begin,int end){this.strategy = strategy;this.pattern = pattern;this.replaceChar = replaceChar;this.begin = begin;this.end = end;}@Overridepublic void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {/// 默认使用正则脱敏、 begin、end 不为空,则策略脱敏if(begin == 0 && end == 0){gen.writeString(strategy.desensitizationByPattern(value,pattern,replaceChar));}else{gen.writeString(strategy.desensitization(value,begin,end));}}@Override@SneakyThrowspublic JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {if (beanProperty != null) {// 非 String 类直接跳过if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {SensitiveInfo sensitiveInfo = beanProperty.getAnnotation(SensitiveInfo.class);if (sensitiveInfo == null) {sensitiveInfo = beanProperty.getContextAnnotation(SensitiveInfo.class);}if (sensitiveInfo != null) {Class<? extends IStrategy> clazz = sensitiveInfo.strategy();// 如果能得到注解,就将注解的 value 传入 SensitiveInfoSerializereturn new SensitiveInfoSerialize(clazz.getDeclaredConstructor().newInstance(),sensitiveInfo.pattern(),sensitiveInfo.replaceChar(),sensitiveInfo.begin(),sensitiveInfo.end());}return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);}}return serializerProvider.findNullValueSerializer(null);}}
/*** 脱敏信息*/
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveInfoSerialize.class)
@Inherited
public @interface SensitiveInfo {/*** 脱敏策略* @return*/Class<? extends IStrategy> strategy() default DefaultSensitiveStrategy.class;/*** 输入格式,使用正则表达式, 优先级大于value** @return 格式*/String pattern() default "";/*** 替换目标字符, 优先级大于value** @return 替换目标字符串*/String replaceChar() default "";/*** 开始显示几位* @return*/int begin() default 0;/*** 结束显示几位* @return*/int end() default 0;
}
/*** 中文姓名脱敏**/
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@SensitiveInfo(strategy = com.adru.sensitive.strategy.SensitiveChineseName.class, pattern = "(?<=.{1}).",replaceChar = "*")
@JacksonAnnotationsInside
public @interface SensitiveChineseName {}

5.测试

定义一个测试类

/*** 用户实体**/
@Data
@Builder
public class UserEntity implements Serializable {/*** 中文姓名--正则*/@SensitiveChineseNameprivate String userNamePattern;/*** 中文姓名--长度*/@SensitiveInfo(strategy = com.adru.sensitive.strategy.SensitiveChineseName.class, begin = 1)private String userNameLength;
}
	@Testpublic void test() {UserEntity userEntity = UserEntity.builder().userNamePattern("张三丰").userNameLength("张三丰").build();log.info(JsonMapper.nonNullMapper().toJson(userEntity));}

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

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

相关文章

Docker容器与虚拟化技术:OpenEuler 部署 Prometheus 与 Grafana

目录 一、实验 1.环境 2.OpenEuler 部署 Prometheus 3.OpenEuler 部署 Grafana 4.使用cpolar内网穿透 二、问题 1.拉取镜像失败 2.如何导入Grafana监控模板&#xff08;ES&#xff09; 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 系统架构版本IP备注…

基于springboot实现甘肃非物质文化网站系统项目【项目源码+论文说明】

摘要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本甘肃非物质文化网站就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信…

vscode的源码插件GitHub Repositories

打铁还需自身硬&#xff0c;需要不断提升自我&#xff0c;提升自我的一种方式就是看源码&#xff0c;站在更高的维度去理解底层原理&#xff0c;以便以后更好的开发和解决问题&#xff0c;由于源码一个动不动就是几个G甚至十几个G&#xff0c;如果一个个源码下载下来&#xff0…

探索K-近邻算法(KNN):原理、实践应用与文本分类实战

第一部分&#xff1a;引言与背景 KNN算法在机器学习领域的重要性及其地位 KNN算法作为机器学习中的基石之一&#xff0c;由于其概念直观、易于理解并且不需要复杂的模型训练过程&#xff0c;被广泛应用于多种场景。它在监督学习中占据着特殊的位置&#xff0c;尤其适用于实时…

Flutter Boost 3

社区的 issue 没有收敛的趋势。 设计过于复杂&#xff0c;概念太多。这让一个新手看 FlutterBoost 的代码很吃力。 这些问题促使我们重新梳理设计&#xff0c;为了彻底解决这些顽固的问题&#xff0c;我们做一次大升级&#xff0c;我们把这次升级命名为 FlutterBoost 3.0&am…

鸡尾酒排序解读

在数据处理的海洋中&#xff0c;排序算法无疑是引领我们探索数据规律的灯塔。今天&#xff0c;我们要探讨的是一种有趣且独特的排序算法——鸡尾酒排序。鸡尾酒排序&#xff0c;也被称为定向冒泡排序、双冒泡排序或搅拌排序&#xff0c;是冒泡排序的一种变体&#xff0c;它通过…

真--个人收款系统方案

此文主要说明方案&#xff0c;无代码部分 前言: 有个个人项目需要接入vip系统&#xff0c;我们发现微信、支付宝的官方API主要服务商户&#xff0c;而市面上的“个人收款系统”也往往不符合我们的需求。不过&#xff0c;每次支付时通知栏的信息给了我灵感。走投无路&#xff0…

基于GD32的简易数字示波器(2)- 原理图设计

这期记录的是项目实战&#xff0c;做一个简易的数字示波器。 教程来源于嘉立创&#xff0c;202&#xff1a;简易数字示波器项目文档 语雀 下图为示波器的指标 具有选择交流耦合还是直流耦合功能、输入信号不衰减或衰减50倍 输入频率理论最大800KHz输入幅值&#xff08;不衰…

蓝凌OA单点登录实现方案:以统一身份管理提升效率与安全新举措

蓝凌OA的优势与挑战 在数字化浪潮的推动下&#xff0c;企业对于高效、安全的身份管理需求愈发迫切。蓝凌OA系统&#xff0c;以其出色的流程管理和协同办公能力&#xff0c;已经成为众多企业实现数字化转型的重要工具。然而&#xff0c;随着企业信息化建设的不断深入&#xff0…

非关系型数据库------------Redis的安装和部署

目录 一、关系型数据库与非关系型数据库 1.1关系型数据库 1.2非关系型数据库 1.2.1非关系型数据库产生背景 1.3关系型非关系型区别 1.4客户访问时&#xff0c;关系型数据库与redis的工作过程 二、Redis 2.1redis简介 2.2Redis命中机制和淘汰机制 2.3Redis 具有以下优…

RobotFramework测试框架(2)-测试用例

创建测试数据 测试数据语法 这里的测试数据就是指的测试用例。 测试文件组织 测试用例的组织层次结构如下&#xff1a; 在测试用例文件&#xff08; test case file &#xff09;中建立测试用例 一个测试文件自动的建成一个包含了这些测试用例的测试集&#xff08; test s…

【Linux】UDP编程{诸多编程接口/三版本服务器/编程常见问题}

文章目录 0.预备知识0.1套接字0.2TCP/UDP0.3大小端问题 1.socket 常见API1.1socket1.2各个接口1.3int bind();1.3网络头文件四件套1.4bzero1.5recvfrom1.6sendto() 2.UDP编程2.1服务器编程2.2客户端编程2.3运行测试2.3.1本机通信2.3.2popen2.3.3strcasestr2.3.4回顾C11智能指针…