什么是數(shù)據(jù)脫敏
開(kāi)胃菜
使用 Hutool 工具類(lèi)實(shí)現(xiàn)數(shù)據(jù)掩碼
使用 Jackson 進(jìn)行數(shù)據(jù)序列化脫敏
注解實(shí)現(xiàn)數(shù)據(jù)脫敏
1、定義一個(gè)注解
2、創(chuàng)建一個(gè)枚舉類(lèi)
3、創(chuàng)建我們的自定義序列化類(lèi)
4、測(cè)試
后記
本文主要分享什么是數(shù)據(jù)脫敏,如何優(yōu)雅的在項(xiàng)目中運(yùn)用一個(gè)注解實(shí)現(xiàn)數(shù)據(jù)脫敏,為項(xiàng)目進(jìn)行賦能。希望能給你們帶來(lái)幫助。
什么是數(shù)據(jù)脫敏
數(shù)據(jù)脫敏是一種通過(guò)去除或替換敏感數(shù)據(jù)中的部分信息,以保護(hù)數(shù)據(jù)隱私和安全的技術(shù)。其主要目的是確保數(shù)據(jù)仍然可以在各種場(chǎng)景中使用,同時(shí)保護(hù)敏感信息,防止數(shù)據(jù)泄露和濫用。數(shù)據(jù)脫敏通常用于處理包含個(gè)人身份信息和其他敏感信息的數(shù)據(jù)集,如手機(jī)號(hào)、姓名、地址、銀行卡、身份證號(hào)、車(chē)牌號(hào)等等。
在數(shù)據(jù)脫敏過(guò)程中,通常會(huì)采用不同的算法和技術(shù),以根據(jù)不同的需求和場(chǎng)景對(duì)數(shù)據(jù)進(jìn)行處理。例如,對(duì)于身份證號(hào)碼,可以使用掩碼算法(masking)將前幾位數(shù)字保留,其他位用“X”或"*"代替;對(duì)于姓名,可以使用偽造(pseudonymization)算法,將真實(shí)姓名替換成隨機(jī)生成的假名。
下面我講為大家?guī)?lái)數(shù)據(jù)脫敏掩碼操作,讓我們一起學(xué)起來(lái)吧。
基于 Spring Boot + MyBatis Plus + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶(hù)小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶(hù)、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能
項(xiàng)目地址:https://github.com/YunaiV/ruoyi-vue-pro
視頻教程:https://doc.iocoder.cn/video/
開(kāi)胃菜
下面給大家介紹的是使用兩種不同的工具類(lèi)進(jìn)行數(shù)據(jù)脫敏,而我們今天的主題使用一個(gè)注解解決數(shù)據(jù)脫敏問(wèn)題的主要兩個(gè)工具類(lèi)。來(lái)跟著我學(xué)習(xí)吧。
使用 Hutool 工具類(lèi)實(shí)現(xiàn)數(shù)據(jù)掩碼
比喻說(shuō)我們現(xiàn)在要對(duì)手機(jī)號(hào)進(jìn)行數(shù)據(jù)脫敏,前三后四不掩碼,其他全部用 * 進(jìn)行掩碼
如下圖代碼所示,
我們定義了一個(gè)手機(jī)號(hào):17677772345,需要進(jìn)行數(shù)據(jù)脫敏。
調(diào)用的 Hutool 的信息脫敏工具類(lèi)。

我們運(yùn)行一下看看結(jié)果。一個(gè)簡(jiǎn)單的數(shù)據(jù)脫敏就實(shí)現(xiàn)了。

Hutool 信息脫敏工具類(lèi)
根據(jù)上面的一個(gè) Demo,大家可以看到我使用了 Hutool 的信息脫敏工具類(lèi)進(jìn)行對(duì)手機(jī)號(hào)掩碼脫敏。那么讓我們一起看看 Hutool 信息脫敏的工具類(lèi)吧。
官網(wǎng)文檔:
https://hutool.cn/docs/#/core/工具類(lèi)/信息脫敏工具-DesensitizedUtil
看一下官網(wǎng)的介紹,支持多種脫敏數(shù)據(jù)類(lèi)型,滿(mǎn)足我們大部分需求,如果需要自定義還提供了自定義的方法實(shí)現(xiàn)。

下面是里面定義號(hào)的脫敏規(guī)則,直接調(diào)用就可以實(shí)現(xiàn)簡(jiǎn)單的數(shù)據(jù)脫敏,這里給大家介紹是因?yàn)槲覀兘裉煲o大家?guī)?lái)的注解實(shí)現(xiàn)數(shù)據(jù)脫敏核心就是利用我們的 Hutool 提供的工具類(lèi)實(shí)現(xiàn),支持自定義隱藏。

使用 Jackson 進(jìn)行數(shù)據(jù)序列化脫敏
首先創(chuàng)建一個(gè)實(shí)體類(lèi),此實(shí)體類(lèi)只有一個(gè)測(cè)試的手機(jī)號(hào)。
注解的講解:
@Data:lombok 的注解生成 get,set 等等方法。
@JsonSerialize(using = TestJacksonSerialize.class):該注解的作用就是可自定義序列化,可以用在注解上,方法上,字段上,類(lèi)上,運(yùn)行時(shí)生效等等,根據(jù)提供的序列化類(lèi)里面的重寫(xiě)方法實(shí)現(xiàn)自定義序列化。可以看下下面的源碼,有興趣的朋友可以去了解一下,也能解決我們?nèi)粘i_(kāi)發(fā)中很多場(chǎng)景。

@Data publicclassTestDTOimplementsSerializable{ /** *手機(jī)號(hào) */ @JsonSerialize(using=TestJacksonSerialize.class) privateStringphone; }
然后創(chuàng)建一個(gè) TestJacksonSerialize 類(lèi)實(shí)現(xiàn)自定義序列化。
此類(lèi)主要繼承 JsonSerializer,因?yàn)槲覀冞@里需要序列化的類(lèi)型是 String 泛型就選擇 String。注意如果你使用此注解作用在類(lèi)上的話(huà),這里就是你要序列化的類(lèi)。
重寫(xiě)序列化方法,里面的實(shí)現(xiàn)很簡(jiǎn)單就是調(diào)用我們的 Hutool 工具類(lèi)進(jìn)行手機(jī)號(hào)數(shù)據(jù)脫敏。
publicclassTestJacksonSerializeextendsJsonSerializer{ @Override @SneakyThrows publicvoidserialize(Stringstr,JsonGeneratorjsonGenerator,SerializerProviderserializerProvider){ //使用我們的hutool工具類(lèi)進(jìn)行手機(jī)號(hào)脫敏 jsonGenerator.writeString(DesensitizedUtil.fixedPhone(String.valueOf(str))); } }
讓我們測(cè)試一下吧,因?yàn)榇俗⒔馐沁\(yùn)行時(shí)生效,我們定義一個(gè)接口來(lái)測(cè)試。
@RestController @RequestMapping("/test") publicclassTestApi{ @GetMapping publicTestDTOtest(){ TestDTOtestDTO=newTestDTO(); testDTO.setPhone("17677772345"); returntestDTO; } }

可以看到測(cè)試成功,經(jīng)過(guò)上面的兩個(gè)工具類(lèi)的介紹,聯(lián)想一下我們?cè)趺赐ㄟ^(guò)兩個(gè)工具類(lèi)定義一個(gè)自己的注解實(shí)現(xiàn)數(shù)據(jù)脫敏呢。
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶(hù)小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶(hù)、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能
項(xiàng)目地址:https://github.com/YunaiV/yudao-cloud
視頻教程:https://doc.iocoder.cn/video/
注解實(shí)現(xiàn)數(shù)據(jù)脫敏
我們考慮一下,工具類(lèi)現(xiàn)在有了,那么我們?cè)趺慈?shí)現(xiàn)一個(gè)注解優(yōu)雅的解決數(shù)據(jù)脫敏呢?
請(qǐng)看下文,讓我?guī)Т蠹乙黄饘W(xué)習(xí)。
1、定義一個(gè)注解
定義一個(gè) Desensitization 注解。
@Retention(RetentionPolicy.RUNTIME):運(yùn)行時(shí)生效。
@Target(ElementType.FIELD):可用在字段上。
@JacksonAnnotationsInside:此注解可以點(diǎn)進(jìn)去看一下是一個(gè)元注解,主要是用戶(hù)打包其他注解一起使用。
@JsonSerialize:上面說(shuō)到過(guò),該注解的作用就是可自定義序列化,可以用在注解上,方法上,字段上,類(lèi)上,運(yùn)行時(shí)生效等等,根據(jù)提供的序列化類(lèi)里面的重寫(xiě)方法實(shí)現(xiàn)自定義序列化。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using=DesensitizationSerialize.class)
public@interfaceDesensitization{
/**
*脫敏數(shù)據(jù)類(lèi)型,只要在CUSTOMER的時(shí)候,startInclude和endExclude生效
*/
DesensitizationTypeEnumtype()defaultDesensitizationTypeEnum.CUSTOMER;
/**
*開(kāi)始位置(包含)
*/
intstartInclude()default0;
/**
*結(jié)束位置(不包含)
*/
intendExclude()default0;
}
可以看到此注解有三個(gè)值,一個(gè)是枚舉類(lèi)定義了我們的脫敏數(shù)據(jù)類(lèi)型。一個(gè)開(kāi)始位置,一個(gè)結(jié)束位置。
枚舉類(lèi)待會(huì)給大家講解,如果選擇了自定義類(lèi)型,下面的開(kāi)始位置,結(jié)束位置才生效。
開(kāi)始結(jié)束位置是我們 Hutool 工具提供的自定義脫敏實(shí)現(xiàn)需要的參數(shù)。可以看此方法,需要提出一點(diǎn)的是此方法硬編碼了掩碼值。如果我們的場(chǎng)景需要其他掩碼值的話(huà)實(shí)現(xiàn)也很簡(jiǎn)單,把 Hutool 的源碼拷出來(lái),代替他的硬編碼,就可以實(shí)現(xiàn)。

2、創(chuàng)建一個(gè)枚舉類(lèi)
此枚舉類(lèi)是我們數(shù)據(jù)脫敏的類(lèi)型,包括了大部分場(chǎng)景。以及可以滿(mǎn)足我們?nèi)粘i_(kāi)發(fā)咯。
publicenumDesensitizationTypeEnum{
//自定義
CUSTOMER,
//用戶(hù)id
USER_ID,
//中文名
CHINESE_NAME,
//身份證號(hào)
ID_CARD,
//座機(jī)號(hào)
FIXED_PHONE,
//手機(jī)號(hào)
MOBILE_PHONE,
//地址
ADDRESS,
//電子郵件
EMAIL,
//密碼
PASSWORD,
//中國(guó)大陸車(chē)牌,包含普通車(chē)輛、新能源車(chē)輛
CAR_LICENSE,
//銀行卡
BANK_CARD
}
3、創(chuàng)建我們的自定義序列化類(lèi)
此類(lèi)是我們數(shù)據(jù)脫敏的關(guān)鍵。主要是繼承了我們的 JsonSerializer,實(shí)現(xiàn)了我的ContextualSerializer。重寫(xiě)了它倆的方法。
@NoArgsConstructor:Lombok 無(wú)參構(gòu)造生成。
@AllArgsConstructor:Lombok 有參生成。
ContextualSerializer:這個(gè)類(lèi)是序列化上下文類(lèi),主要是解決我們這個(gè)地方獲取字段的一些信息,可以看一下源碼,他的實(shí)現(xiàn)類(lèi)有很多,Jackson 提供的 @JsonFormat 注解也是實(shí)現(xiàn)此類(lèi),獲取字段的一些信息進(jìn)行序列化的。有興趣的朋友可以看一下,多看源碼,才能學(xué)到 Jackson 的實(shí)現(xiàn)方法,才能有今天我們的實(shí)現(xiàn)。
兩個(gè)重寫(xiě)的方法解讀:
serialize:重寫(xiě),實(shí)現(xiàn)我們的序列化自定義。
createContextual:序列化上下文方法重寫(xiě),獲取我們的字段一些信息進(jìn)行判斷,然后返回實(shí)例。具體代碼可以看下面代碼,都有注釋噢。
@NoArgsConstructor @AllArgsConstructor publicclassDesensitizationSerializeextendsJsonSerializerimplementsContextualSerializer{ privateDesensitizationTypeEnumtype; privateIntegerstartInclude; privateIntegerendExclude; @Override publicvoidserialize(Stringstr,JsonGeneratorjsonGenerator,SerializerProviderserializerProvider)throwsIOException{ switch(type){ //自定義類(lèi)型脫敏 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; //固定電話(huà)脫敏 caseFIXED_PHONE: jsonGenerator.writeString(DesensitizedUtil.fixedPhone(String.valueOf(str))); break; //手機(jī)號(hào)脫敏 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; //中國(guó)車(chē)牌脫敏 caseCAR_LICENSE: jsonGenerator.writeString(DesensitizedUtil.carLicense(String.valueOf(str))); break; //銀行卡脫敏 caseBANK_CARD: jsonGenerator.writeString(DesensitizedUtil.bankCard(String.valueOf(str))); break; default: } } @Override publicJsonSerializer>createContextual(SerializerProviderserializerProvider,BeanPropertybeanProperty)throwsJsonMappingException{ if(beanProperty!=null){ //判斷數(shù)據(jù)類(lèi)型是否為String類(lèi)型 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){ //創(chuàng)建定義的序列化類(lèi)的實(shí)例并且返回,入?yún)樽⒔舛x的type,開(kāi)始位置,結(jié)束位置。 returnnewDesensitizationSerialize(desensitization.type(),desensitization.startInclude(), desensitization.endExclude()); } } returnserializerProvider.findValueSerializer(beanProperty.getType(),beanProperty); } returnserializerProvider.findNullValueSerializer(null); } }
4、測(cè)試
創(chuàng)建一個(gè)測(cè)試注解的 DTO,此測(cè)試如下。
@Data
publicclassTestAnnotationDTOimplementsSerializable{
/**
*自定義
*/
@Desensitization(type=DesensitizationTypeEnum.CUSTOMER,startInclude=5,endExclude=10)
privateStringcustom;
/**
*手機(jī)號(hào)
*/
@Desensitization(type=DesensitizationTypeEnum.MOBILE_PHONE)
privateStringphone;
/**
*郵箱
*/
@Desensitization(type=DesensitizationTypeEnum.EMAIL)
privateStringemail;
/**
*身份證
*/
@Desensitization(type=DesensitizationTypeEnum.ID_CARD)
privateStringidCard;
}
新增測(cè)試接口:
@GetMapping("/test-annotation")
publicTestAnnotationDTOtestAnnotation(){
TestAnnotationDTOtestAnnotationDTO=newTestAnnotationDTO();
testAnnotationDTO.setPhone("17677772345");
testAnnotationDTO.setCustom("111111111111111111");
testAnnotationDTO.setEmail("1433926101@qq.com");
testAnnotationDTO.setIdCard("4444199810015555");
returntestAnnotationDTO;
}
測(cè)試一下看看效果。如下圖所示,完美!

項(xiàng)目 pom 文件
4.0.0 org.springframework.boot spring-boot-starter-parent 2.7.10 com.jiaqing tool-desensitization 0.0.1-SNAPSHOT tool-desensitization 數(shù)據(jù)脫敏 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
后記
今天給大家?guī)?lái)的是如何實(shí)現(xiàn)一個(gè)注解進(jìn)行數(shù)據(jù)脫敏。
責(zé)任編輯:彭菁
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7342瀏覽量
94943 -
小程序
+關(guān)注
關(guān)注
1文章
243瀏覽量
13437
原文標(biāo)題:太強(qiáng)了!一個(gè)注解解決數(shù)據(jù)脫敏問(wèn)題
文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
實(shí)現(xiàn) Labview 和SQL server進(jìn)行數(shù)據(jù)的讀取和寫(xiě)入
請(qǐng)問(wèn)AD7606能否實(shí)現(xiàn)使用DMA進(jìn)行數(shù)據(jù)讀取?
DMA進(jìn)行數(shù)據(jù)傳輸和CPU進(jìn)行數(shù)據(jù)傳輸?shù)囊蓡?wèn)
AD7606能否實(shí)現(xiàn)使用DMA進(jìn)行數(shù)據(jù)讀取?
如何更好地進(jìn)行數(shù)據(jù)采集
使用Spring自定義注解的實(shí)現(xiàn)
SQL/JAVA/mybatisplus數(shù)據(jù)脫敏實(shí)現(xiàn)原理
成功進(jìn)行數(shù)據(jù)整合的案例
數(shù)據(jù)脫敏具體指的是什么?又是如何進(jìn)行數(shù)據(jù)脫敏
數(shù)據(jù)脫敏技術(shù)定義及實(shí)施過(guò)程解析
如何實(shí)現(xiàn)SpringBoot項(xiàng)目中的隱私數(shù)據(jù)脫敏呢
什么是數(shù)據(jù)脫敏?常用的脫敏規(guī)則有哪些呢?
SpringBoot采用JsonSerializer和Aop實(shí)現(xiàn)可控制的數(shù)據(jù)脫敏
盤(pán)點(diǎn)一下PostgreSQL的幾種常用脫敏方式
如何實(shí)現(xiàn)一個(gè)注解進(jìn)行數(shù)據(jù)脫敏
評(píng)論