0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何实现一个注解进行数据脱敏

jf_ro2CN3Fa 来源:芋道源码 2023-06-14 09:37 次阅读

什么是数据脱敏

开胃菜

使用 Hutool 工具类实现数据掩码

使用 Jackson 进行数据序列化脱敏

注解实现数据脱敏

1、定义一个注解

2、创建一个枚举类

3、创建我们的自定义序列化类

4、测试

后记

本文主要分享什么是数据脱敏,如何优雅的在项目中运用一个注解实现数据脱敏,为项目进行赋能。希望能给你们带来帮助。

什么是数据脱敏

数据脱敏是一种通过去除或替换敏感数据中的部分信息,以保护数据隐私和安全的技术。其主要目的是确保数据仍然可以在各种场景中使用,同时保护敏感信息,防止数据泄露和滥用。数据脱敏通常用于处理包含个人身份信息和其他敏感信息的数据集,如手机号、姓名、地址、银行卡、身份证号、车牌号等等。

在数据脱敏过程中,通常会采用不同的算法和技术,以根据不同的需求和场景对数据进行处理。例如,对于身份证号码,可以使用掩码算法(masking)将前几位数字保留,其他位用“X”或"*"代替;对于姓名,可以使用伪造(pseudonymization)算法,将真实姓名替换成随机生成的假名。

下面我讲为大家带来数据脱敏掩码操作,让我们一起学起来吧。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

项目地址:https://github.com/YunaiV/ruoyi-vue-pro

视频教程:https://doc.iocoder.cn/video/

开胃菜

下面给大家介绍的是使用两种不同的工具类进行数据脱敏,而我们今天的主题使用一个注解解决数据脱敏问题的主要两个工具类。来跟着我学习吧。

使用 Hutool 工具类实现数据掩码

比喻说我们现在要对手机号进行数据脱敏,前三后四不掩码,其他全部用 * 进行掩码

如下图代码所示,

我们定义了一个手机号:17677772345,需要进行数据脱敏。

调用的 Hutool 的信息脱敏工具类。

7f333bf6-0a53-11ee-962d-dac502259ad0.jpg

我们运行一下看看结果。一个简单的数据脱敏就实现了。

7f408be4-0a53-11ee-962d-dac502259ad0.jpg

Hutool 信息脱敏工具类

根据上面的一个 Demo,大家可以看到我使用了 Hutool 的信息脱敏工具类进行对手机号掩码脱敏。那么让我们一起看看 Hutool 信息脱敏的工具类吧。

官网文档:

https://hutool.cn/docs/#/core/工具类/信息脱敏工具-DesensitizedUtil

看一下官网的介绍,支持多种脱敏数据类型,满足我们大部分需求,如果需要自定义还提供了自定义的方法实现。

7f505196-0a53-11ee-962d-dac502259ad0.jpg

下面是里面定义号的脱敏规则,直接调用就可以实现简单的数据脱敏,这里给大家介绍是因为我们今天要给大家带来的注解实现数据脱敏核心就是利用我们的 Hutool 提供的工具类实现,支持自定义隐藏。

7f671cd2-0a53-11ee-962d-dac502259ad0.jpg

使用 Jackson 进行数据序列化脱敏

首先创建一个实体类,此实体类只有一个测试的手机号。

注解的讲解:

@Data:lombok 的注解生成 get,set 等等方法。

@JsonSerialize(using = TestJacksonSerialize.class):该注解的作用就是可自定义序列化,可以用在注解上,方法上,字段上,类上,运行时生效等等,根据提供的序列化类里面的重写方法实现自定义序列化。可以看下下面的源码,有兴趣的朋友可以去了解一下,也能解决我们日常开发中很多场景。

7f8985d8-0a53-11ee-962d-dac502259ad0.jpg

@Data
publicclassTestDTOimplementsSerializable{
/**
*手机号
*/
@JsonSerialize(using=TestJacksonSerialize.class)
privateStringphone;
}

然后创建一个 TestJacksonSerialize 类实现自定义序列化。

此类主要继承 JsonSerializer,因为我们这里需要序列化的类型是 String 泛型就选择 String。注意如果你使用此注解作用在类上的话,这里就是你要序列化的类。

重写序列化方法,里面的实现很简单就是调用我们的 Hutool 工具类进行手机号数据脱敏。

publicclassTestJacksonSerializeextendsJsonSerializer{

@Override
@SneakyThrows
publicvoidserialize(Stringstr,JsonGeneratorjsonGenerator,SerializerProviderserializerProvider){
//使用我们的hutool工具类进行手机号脱敏
jsonGenerator.writeString(DesensitizedUtil.fixedPhone(String.valueOf(str)));
}
}

让我们测试一下吧,因为此注解是运行时生效,我们定义一个接口来测试。

@RestController
@RequestMapping("/test")
publicclassTestApi{

@GetMapping
publicTestDTOtest(){
TestDTOtestDTO=newTestDTO();
testDTO.setPhone("17677772345");
returntestDTO;
}
}
7faacf40-0a53-11ee-962d-dac502259ad0.jpg

可以看到测试成功,经过上面的两个工具类的介绍,联想一下我们怎么通过两个工具类定义一个自己的注解实现数据脱敏呢。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

项目地址:https://github.com/YunaiV/yudao-cloud

视频教程:https://doc.iocoder.cn/video/

注解实现数据脱敏

我们考虑一下,工具类现在有了,那么我们怎么去实现一个注解优雅的解决数据脱敏呢?

请看下文,让我带大家一起学习。

1、定义一个注解

定义一个 Desensitization 注解。

@Retention(RetentionPolicy.RUNTIME):运行时生效。

@Target(ElementType.FIELD):可用在字段上。

@JacksonAnnotationsInside:此注解可以点进去看一下是一个元注解,主要是用户打包其他注解一起使用。

@JsonSerialize:上面说到过,该注解的作用就是可自定义序列化,可以用在注解上,方法上,字段上,类上,运行时生效等等,根据提供的序列化类里面的重写方法实现自定义序列化。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using=DesensitizationSerialize.class)
public@interfaceDesensitization{
/**
*脱敏数据类型,只要在CUSTOMER的时候,startInclude和endExclude生效
*/
DesensitizationTypeEnumtype()defaultDesensitizationTypeEnum.CUSTOMER;

/**
*开始位置(包含)
*/
intstartInclude()default0;

/**
*结束位置(不包含)
*/
intendExclude()default0;
}

可以看到此注解有三个值,一个是枚举类定义了我们的脱敏数据类型。一个开始位置,一个结束位置。

枚举类待会给大家讲解,如果选择了自定义类型,下面的开始位置,结束位置才生效。

开始结束位置是我们 Hutool 工具提供的自定义脱敏实现需要的参数。可以看此方法,需要提出一点的是此方法硬编码了掩码值。如果我们的场景需要其他掩码值的话实现也很简单,把 Hutool 的源码拷出来,代替他的硬编码,就可以实现。

7fe917be-0a53-11ee-962d-dac502259ad0.jpg

2、创建一个枚举类

此枚举类是我们数据脱敏的类型,包括了大部分场景。以及可以满足我们日常开发咯。

publicenumDesensitizationTypeEnum{
//自定义
CUSTOMER,
//用户id
USER_ID,
//中文名
CHINESE_NAME,
//身份证号
ID_CARD,
//座机号
FIXED_PHONE,
//手机号
MOBILE_PHONE,
//地址
ADDRESS,
//电子邮件
EMAIL,
//密码
PASSWORD,
//中国大陆车牌,包含普通车辆、新能源车辆
CAR_LICENSE,
//银行卡
BANK_CARD
}

3、创建我们的自定义序列化类

此类是我们数据脱敏的关键。主要是继承了我们的 JsonSerializer,实现了我的ContextualSerializer。重写了它俩的方法。

@NoArgsConstructor:Lombok 无参构造生成。

@AllArgsConstructor:Lombok 有参生成。

ContextualSerializer:这个类是序列化上下文类,主要是解决我们这个地方获取字段的一些信息,可以看一下源码,他的实现类有很多,Jackson 提供的 @JsonFormat 注解也是实现此类,获取字段的一些信息进行序列化的。有兴趣的朋友可以看一下,多看源码,才能学到 Jackson 的实现方法,才能有今天我们的实现。

两个重写的方法解读:

serialize:重写,实现我们的序列化自定义。

createContextual:序列化上下文方法重写,获取我们的字段一些信息进行判断,然后返回实例。具体代码可以看下面代码,都有注释噢。

@NoArgsConstructor
@AllArgsConstructor
publicclassDesensitizationSerializeextendsJsonSerializerimplementsContextualSerializer{
privateDesensitizationTypeEnumtype;

privateIntegerstartInclude;

privateIntegerendExclude;
@Override
publicvoidserialize(Stringstr,JsonGeneratorjsonGenerator,SerializerProviderserializerProvider)throwsIOException{
switch(type){
//自定义类型脱敏
caseCUSTOMER:
jsonGenerator.writeString(CharSequenceUtil.hide(str,startInclude,endExclude));
break;
//userId脱敏
caseUSER_ID:
jsonGenerator.writeString(String.valueOf(DesensitizedUtil.userId()));
break;
//中文姓名脱敏
caseCHINESE_NAME:
jsonGenerator.writeString(DesensitizedUtil.chineseName(String.valueOf(str)));
break;
//身份证脱敏
caseID_CARD:
jsonGenerator.writeString(DesensitizedUtil.idCardNum(String.valueOf(str),1,2));
break;
//固定电话脱敏
caseFIXED_PHONE:
jsonGenerator.writeString(DesensitizedUtil.fixedPhone(String.valueOf(str)));
break;
//手机号脱敏
caseMOBILE_PHONE:
jsonGenerator.writeString(DesensitizedUtil.mobilePhone(String.valueOf(str)));
break;
//地址脱敏
caseADDRESS:
jsonGenerator.writeString(DesensitizedUtil.address(String.valueOf(str),8));
break;
//邮箱脱敏
caseEMAIL:
jsonGenerator.writeString(DesensitizedUtil.email(String.valueOf(str)));
break;
//密码脱敏
casePASSWORD:
jsonGenerator.writeString(DesensitizedUtil.password(String.valueOf(str)));
break;
//中国车牌脱敏
caseCAR_LICENSE:
jsonGenerator.writeString(DesensitizedUtil.carLicense(String.valueOf(str)));
break;
//银行卡脱敏
caseBANK_CARD:
jsonGenerator.writeString(DesensitizedUtil.bankCard(String.valueOf(str)));
break;
default:
}

}

@Override
publicJsonSerializercreateContextual(SerializerProviderserializerProvider,BeanPropertybeanProperty)throwsJsonMappingException{
if(beanProperty!=null){
//判断数据类型是否为String类型
if(Objects.equals(beanProperty.getType().getRawClass(),String.class)){
//获取定义的注解
Desensitizationdesensitization=beanProperty.getAnnotation(Desensitization.class);
//为null
if(desensitization==null){
desensitization=beanProperty.getContextAnnotation(Desensitization.class);
}
//不为null
if(desensitization!=null){
//创建定义的序列化类的实例并且返回,入参为注解定义的type,开始位置,结束位置。
returnnewDesensitizationSerialize(desensitization.type(),desensitization.startInclude(),
desensitization.endExclude());
}
}

returnserializerProvider.findValueSerializer(beanProperty.getType(),beanProperty);
}
returnserializerProvider.findNullValueSerializer(null);
}
}

4、测试

创建一个测试注解的 DTO,此测试如下。

@Data
publicclassTestAnnotationDTOimplementsSerializable{
/**
*自定义
*/
@Desensitization(type=DesensitizationTypeEnum.CUSTOMER,startInclude=5,endExclude=10)
privateStringcustom;
/**
*手机号
*/
@Desensitization(type=DesensitizationTypeEnum.MOBILE_PHONE)
privateStringphone;
/**
*邮箱
*/
@Desensitization(type=DesensitizationTypeEnum.EMAIL)
privateStringemail;
/**
*身份证
*/
@Desensitization(type=DesensitizationTypeEnum.ID_CARD)
privateStringidCard;
}

新增测试接口:

@GetMapping("/test-annotation")
publicTestAnnotationDTOtestAnnotation(){
TestAnnotationDTOtestAnnotationDTO=newTestAnnotationDTO();
testAnnotationDTO.setPhone("17677772345");
testAnnotationDTO.setCustom("111111111111111111");
testAnnotationDTO.setEmail("1433926101@qq.com");
testAnnotationDTO.setIdCard("4444199810015555");
returntestAnnotationDTO;
}

测试一下看看效果。如下图所示,完美!

8002862c-0a53-11ee-962d-dac502259ad0.jpg

项目 pom 文件




4.0.0

org.springframework.boot
spring-boot-starter-parent
2.7.10

 

com.jiaqing
tool-desensitization
0.0.1-SNAPSHOT
tool-desensitization
数据脱敏

1.8
5.8.5



org.springframework.boot
spring-boot-starter


org.springframework.boot
spring-boot-starter-web


cn.hutool
hutool-core
${hutool.version}


org.projectlombok
lombok
true


org.springframework.boot
spring-boot-starter-test
test

 

org.springframework.boot
spring-boot-starter-json





org.springframework.boot
spring-boot-maven-plugin



org.projectlombok
lombok







后记

今天给大家带来的是如何实现一个注解进行数据脱敏。
责任编辑:彭菁

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据
    +关注

    关注

    8

    文章

    6512

    浏览量

    87601
  • 小程序
    +关注

    关注

    1

    文章

    227

    浏览量

    11844

原文标题:太强了!一个注解解决数据脱敏问题

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    实现 Labview 和SQL server进行数据的读取和写入

    我想实现以下功能:Labview读取SQL server中的表格,鼠标点击选中某行,此行处于被选中状态(颜色变深),点击保存按钮,将实时数组中的
    发表于 09-07 09:25

    请问AD7606能否实现使用DMA进行数据读取?

    因为AD7606它没有内部寄存器,所以我想知道它能否实现使用DMA进行数据读取??
    发表于 01-28 13:47

    请问下怎么实现在CAN总线上进行数据通信?

    本论文主要研究CAN总线的特性及优势,实现在CAN总线上进行数据通信。课题设计并实现的功能模块,可扩展性好,便于升级和维护。有良好的实际应用价值,有利于CAN总线的汽车应用国产化。
    发表于 05-17 06:58

    如何用C++做一个TCP的服务器进行数据观察及采集呢

    如何用C++做一个TCP的服务器进行数据观察及采集呢?有哪些设计步骤?
    发表于 12-23 09:41

    使用STM32单片机用IIC协议对AT24C02进行数据写入

    前面讲了IIC协议的介绍和IIC协议的编程实现,接下来我们来做一个关于IIC的小项目。、项目的实现功能:1、使用STM32单片机用IIC协议对AT24C02
    发表于 02-10 06:42

    DMA进行数据传输和CPU进行数据传输的疑问

    原先的总线矩阵+仲裁器结构中的数据总线进行数据传输的? 接上一个问题,如果是的话,那么当进行DMA数据传输时,必定是需要占用
    发表于 05-25 17:18

    AD7606能否实现使用DMA进行数据读取?

    因为AD7606它没有内部寄存器,所以我想知道它能否实现使用DMA进行数据读取??
    发表于 12-08 08:22

    SQL/JAVA/mybatisplus数据脱敏实现原理

    MYSQL(电话号码,身份证)数据脱敏实现
    的头像 发表于 06-14 17:09 3129次阅读

    数据脱敏具体指的是什么?又是如何进行数据脱敏

    一般来说,数据脱敏技术指的是在对敏感数据进行处理的过程中,通过数据变形(将数据变成模型想要的结构
    发表于 11-09 09:14 1.1w次阅读

    如何实现SpringBoot项目中的隐私数据脱敏

    数据脱敏:把系统里的一些敏感数据进行加密处理后再返回,达到保护隐私作用
    的头像 发表于 01-08 10:25 1386次阅读

    什么是数据脱敏?常用的脱敏规则有哪些呢?

    数据脱敏,指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护。
    的头像 发表于 08-15 10:04 1w次阅读
    什么是<b class='flag-5'>数据</b><b class='flag-5'>脱敏</b>?常用的<b class='flag-5'>脱敏</b>规则有哪些呢?

    SpringBoot采用JsonSerializer和Aop实现可控制的数据脱敏

    的确实现数据脱敏,但是有个问题现在的脱敏针对的是 只要对该实体类进行了使用返回的接口,中的数据
    的头像 发表于 11-06 16:15 431次阅读
    SpringBoot采用JsonSerializer和Aop<b class='flag-5'>实现</b>可控制的<b class='flag-5'>数据</b><b class='flag-5'>脱敏</b>

    盘点一下PostgreSQL的几种常用脱敏方式

    PostgreSQL Anonymizer 实现动态脱敏的方式是通过将定义某个角色为 "MASKED" 以及脱敏规则。被授予 "MASKED" 角色的用户将无法访问原始数据,而其他角色
    的头像 发表于 12-05 09:59 230次阅读
    盘点一下PostgreSQL的几种常用<b class='flag-5'>脱敏</b>方式

    隧道没信号怎么进行数据采集

    隧道没信号怎么进行数据采集
    的头像 发表于 12-06 13:27 320次阅读

    数据脱敏的3种常见方案,好用到爆!

    数据脱敏插件,目前支持地址脱敏、银行卡号脱敏、中文姓名脱敏、固话脱敏、身份证号
    的头像 发表于 02-25 16:14 362次阅读
    <b class='flag-5'>数据</b><b class='flag-5'>脱敏</b>的3种常见方案,好用到爆!