SpringBoot中優雅的實現隱私數據脫敏(提供Gitee源碼)

前言:在實際項目開發中,可能會對一些用戶的隱私信息進行脫敏操作,傳統的方式很多都是用replace方法進行手動替換,這樣會由很多冗余的代碼并且后續也不好維護,本期就講解一下如何在SpringBoot中優雅的通過序列化的方式去實現數據的脫敏操作!

目錄

一、導入pom依賴

二、DesensitizationEnum枚舉類

三、Desensitization自定義注解

四、DesensitizationSerialize脫敏序列化器

五、User實體類

六、UserController請求層

七、運行測試

八、Gitee源碼

九、總結


一、導入pom依賴

完整代碼:

    <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.18</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

二、DesensitizationEnum枚舉類

在DesensitizationSerialize序列化類中,會根據脫敏注解的type值,也就是DesensitizationEnum 中的類型,來判斷需要使用哪種脫敏方式。

這邊我就簡單定義了5個枚舉類型:

完整代碼:

package com.example.desensitization.constant;public enum DesensitizationEnum {/*** 自定義*/CUSTOM_RULE,/*** 身份證號碼*/ID_CARD_NO,/*** 電話號碼*/PHONE,/*** 地址*/ADDRESS,/*** 銀行卡號*/BANK_CARD_NO,
}

三、Desensitization自定義注解

這個是自定義的注解@Desensitization,用于標注需要進行脫敏的字段。

主要包含以下元注解和屬性

1、@Target(ElementType.FIELD):表示該注解只能用于字段上。

2、@Retention(RetentionPolicy.RUNTIME):表示該注解可以保留到運行時。

3、@JacksonAnnotationsInside:是一個Jackson的元注解,表示該注解可以作為Json序列化的注解。

4、@JsonSerialize:標注使用DesensitizationSerialize來進行序列化。

5、DesensitizationEnum type:需要脫敏的類型,對應枚舉中的脫敏類型。

6、int start/end:可選的起始位置和結束位置,對于脫敏類型為字符串時有效。

完整代碼:

package com.example.desensitization.annotation;import com.example.desensitization.constant.DesensitizationEnum;
import com.example.desensitization.serialize.DesensitizationSerialize;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = DesensitizationSerialize.class)
public @interface Desensitization {DesensitizationEnum type();int start() default 0;int end() default 0;}

四、DesensitizationSerialize脫敏序列化器

1、繼承JsonSerializer<String>JsonSerializer是Jackson的序列化器基類,實現了將對象序列化為JSON的核心方法,這里繼承它是為了實現字符串的自定義序列化。

2、實現ContextualSerializer接口ContextualSerializer可以讓序列化器基于上下文環境進行定制化,實現這個接口后,可以實現createContextual()方法。

關鍵代碼:

@AllArgsConstructor
@NoArgsConstructor
public class DesensitizationSerialize extends JsonSerializer<String> implements ContextualSerializer {private DesensitizationEnum type;private Integer start;private Integer end;
}

自定義序列化器方式可以實現非侵入式的靈活脫敏,對業務代碼零侵入,且不依賴Spring等框架,更適合編寫獨立的應用服務。當然,AOP實現也有其適用場景,可以作為另一種可選方案。

createContextual()方法:

1、Controller的user()方法被調用,構建并返回了一個User對象。

2、開始對User對象進行JSON序列化,會先調用我們定義的DesensitizationSerialize中createContextual()方法,如果這個實體類被createContextual()方法處理過,則以后不會再走該方法,直接走serialize()方法。

3、DesensitizationSerialize會檢查當前類字段是否有@Desensitization注解,如果有N個,則根據注解的type、start和end參數創建N個DesensitizationSerialize實例。

關鍵代碼:

@Overridepublic JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty)throws JsonMappingException {if (beanProperty != null) {// 獲取當前正在處理的字段的類型,判斷如果是 String 類型則進行后續脫敏邏輯處理if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {// 通過 beanProperty 獲取在字段上標注的 @Desensitization 注解Desensitization desensitization = beanProperty.getAnnotation(Desensitization.class);// 如果沒有就嘗試獲取類注解if (desensitization == null) {desensitization = beanProperty.getContextAnnotation(Desensitization.class);}// 不為nullif (desensitization != null) {// 如果獲取到了注解,則根據注解的 type、start 和 end 參數創建 DesensitizationSerialize 實例,這是脫敏處理的序列化器return new DesensitizationSerialize(desensitization.type(), desensitization.start(),desensitization.end());}}// 直接返回默認的序列化器return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);}// 直接返回默認的序列化器return serializerProvider.findNullValueSerializer(null);}

serialize方法:?

JsonGenerator是Jackjson提供的JSON生成器類。在自定義序列化器的serialize()方法中,會傳入JsonGenerator實例。serialize()方法需要通過JsonGenerator將脫敏后的字符串寫入到結果JSON中。

CharSequenceUtil和DesensitizedUtil都是hutool提供的工具類。

整體流程是:

1、根據注解的參數動態選擇脫敏策略。

2、調用對應 Hutool 的脫敏函數處理字符串。

3、將脫敏結果寫入JSON。

關鍵代碼:

    @Overridepublic void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)throws IOException {switch (type){//自定義case CUSTOM_RULE:jsonGenerator.writeString(CharSequenceUtil.hide(s, start, end));break;//身份證case ID_CARD_NO:jsonGenerator.writeString(DesensitizedUtil.idCardNum(s, 2, 6));break;//手機號case PHONE:jsonGenerator.writeString(DesensitizedUtil.mobilePhone(s));break;//地址case ADDRESS:jsonGenerator.writeString(DesensitizedUtil.address(s, 2));break;// 銀行卡脫敏case BANK_CARD_NO:jsonGenerator.writeString(DesensitizedUtil.bankCard(s));break;default:}}

綜上,整體的執行邏輯如下:

1、Controller返回一個實體對象。

2、如果實體對象是第一次進行脫敏,則會調用createContextual()方法。

3、獲取當前實體對象所有使用Desensitization注解的字符串字段,創建對應的DesensitizationSerialize實例,實現脫敏處理的序列化器。

4、執行serialize()方法中switch的處理邏輯,由JsonGenerator將脫敏后的字符串寫入到結果JSON中。

5、返回Json數據。

完整代碼:

package com.example.desensitization.serialize;import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.DesensitizedUtil;
import com.example.desensitization.annotation.Desensitization;
import com.example.desensitization.constant.DesensitizationEnum;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import java.io.IOException;
import java.util.Objects;@AllArgsConstructor
@NoArgsConstructor
public class DesensitizationSerialize extends JsonSerializer<String> implements ContextualSerializer {private DesensitizationEnum type;private Integer start;private Integer end;@Overridepublic void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)throws IOException {switch (type){//自定義case CUSTOM_RULE:jsonGenerator.writeString(CharSequenceUtil.hide(s, start, end));break;//身份證case ID_CARD_NO:jsonGenerator.writeString(DesensitizedUtil.idCardNum(s, 2, 6));break;//手機號case PHONE:jsonGenerator.writeString(DesensitizedUtil.mobilePhone(s));break;//地址case ADDRESS:jsonGenerator.writeString(DesensitizedUtil.address(s, 2));break;// 銀行卡脫敏case BANK_CARD_NO:jsonGenerator.writeString(DesensitizedUtil.bankCard(s));break;default:}}@Overridepublic JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty)throws JsonMappingException {if (beanProperty != null) {// 獲取當前正在處理的字段的類型,判斷如果是 String 類型則進行后續脫敏邏輯處理if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {// 通過 beanProperty 獲取在字段上標注的 @Desensitization 注解Desensitization desensitization = beanProperty.getAnnotation(Desensitization.class);// 如果沒有就嘗試獲取類注解if (desensitization == null) {desensitization = beanProperty.getContextAnnotation(Desensitization.class);}// 不為nullif (desensitization != null) {// 如果獲取到了注解,則根據注解的 type、start 和 end 參數創建 DesensitizationSerialize 實例,這是脫敏處理的序列化器return new DesensitizationSerialize(desensitization.type(), desensitization.start(),desensitization.end());}}// 直接返回默認的序列化器return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);}// 直接返回默認的序列化器return serializerProvider.findNullValueSerializer(null);}
}

五、User實體類

給想要脫敏的字段加上?@Desensitization(type = DesensitizationEnum.枚舉類型)注解即可。

完整代碼:

package com.example.desensitization.domain;import com.example.desensitization.annotation.Desensitization;
import com.example.desensitization.constant.DesensitizationEnum;
import lombok.Builder;
import lombok.Data;@Data
@Builder
public class User {/*** 主鍵*/private String id;/*** 用戶名*/private String name;/*** 身份證號碼*/@Desensitization(type = DesensitizationEnum.ID_CARD_NO)private String idCardNo;/*** 電話號碼*/@Desensitization(type = DesensitizationEnum.PHONE)private String phone;/*** 地址*/@Desensitization(type = DesensitizationEnum.CUSTOM_RULE,start = 2,end = 5)private String address;/*** 銀行卡號*/@Desensitization(type = DesensitizationEnum.BANK_CARD_NO)private String bankCardNo;}

六、UserController請求層

完整代碼:

package com.example.desensitization.controller;import com.example.desensitization.domain.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.UUID;@RestController
@RequestMapping
public class UserController {@GetMapping("/user")public User user(){User user = User.builder().id(UUID.randomUUID().toString()).name("張三").idCardNo("32089809285012823").phone("13919819285").bankCardNo("62427292012731238812").address("江蘇省南通市").build();return user;}}

七、運行測試

瀏覽器直接訪問:http://localhost:8080/user

可以看到隱私的信息都進行了數據脫敏的處理!

八、Gitee源碼

源碼地址:SpringBoot中優雅的實現隱私數據脫敏

九、總結

以上就是我對于SpringBoot中如何優雅的實現隱私數據脫敏的完整教程,如有問題,歡迎評論區留言!?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/43744.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/43744.shtml
英文地址,請注明出處:http://en.pswp.cn/news/43744.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

設計模式之備忘錄模式(Memento)的C++實現

1、備忘錄模式的提出 在軟件功能開發過程中&#xff0c;某些對象的狀態在轉換過程中&#xff0c;由于業務場景需要&#xff0c;要求對象能夠回溯到對象之前某個點的狀態。如果使用一些共有接口來讓其他對象得到對象的狀態&#xff0c;便會暴露對象的實現細節。備忘錄模式是在不…

【學會動態規劃】單詞拆分(24)

目錄 動態規劃怎么學&#xff1f; 1. 題目解析 2. 算法原理 1. 狀態表示 2. 狀態轉移方程 3. 初始化 4. 填表順序 5. 返回值 3. 代碼編寫 寫在最后&#xff1a; 動態規劃怎么學&#xff1f; 學習一個算法沒有捷徑&#xff0c;更何況是學習動態規劃&#xff0c; 跟我…

【模擬集成電路】反饋系統——基礎到進階(一)

【模擬集成電路】反饋系統——基礎到進階 前言1 概述2 反饋電路特性2.1增益靈敏度降低2.2 終端阻抗變化2.3 帶寬拓展2.4 非線性減小 3 放大器分類4 反饋檢測和返回機制4.1 按照檢測物理量分類4.2 按照檢測拓撲連接分類 5 反饋結構分析6 二端口方法7 波特方法6 麥德布魯克方法 前…

VS2015打開Qt的pro項目文件 報錯

QT報錯&#xff1a;Project ERROR: msvc-version.conf loaded but QMAKE_MSC_VER isn‘t set 解決方法&#xff1a; 找到本機安裝的QT路徑&#xff0c;找到“msvc-version.conf”文件&#xff0c;用記事本打開&#xff0c; 在其中添加版本“QMAKE_MSC_VER 1900”保存即可。 …

Kafka基礎及常見面試題

1. 用途 1. 流量削峰 2. 流計算 2. Kafka的核心組件 在Kafka中&#xff0c;Producer、Broker和Consumer是三個關鍵的角色&#xff0c;它們在整個消息傳遞過程中扮演不同的角色和功能&#xff1a;1. **Producer&#xff08;生產者&#xff09;**&#xff1a;生產者是消息的發…

CSS:filter濾鏡 詳解(用法 + 代碼 + 例子 + 效果)

文章目錄 filter 濾鏡blur() 模糊度例子 漸變光暈 brightness() 元素亮度contrast() 對比度grayscale() 元素灰度hue-rorate() 色相opacity() 透明度invert() 反轉顏色saturate() 飽和度 backdrop-filter 蒙版&#xff0c;濾鏡例子 卷軸展開 filter 濾鏡 動圖為效果添加前后對…

界面組件Telerik UI for WinForms R2 2023——擁有VS2022暗黑主題

Telerik UI for WinForms擁有適用Windows Forms的110多個令人驚嘆的UI控件。所有的UI for WinForms控件都具有完整的主題支持&#xff0c;可以輕松地幫助開發人員在桌面和平板電腦應用程序提供一致美觀的下一代用戶體驗。 Telerik UI for WinForms R2 2023于今年6月份發布&…

Blender 混合現實3D模型制作指南【XR】

本教程分步展示如何&#xff1a; 減少 3D 模型的多邊形數量&#xff0c;使其滿足 Microsoft Dynamics 365 Guides 和使用 Microsoft Power Apps 創建的應用程序中包含的混合現實組件的特定性能目標的性能需求。將 3D 模型的多種材質&#xff08;顏色&#xff09;組合成可應用于…

?Kubernetes的演變:從etcd到分布式SQL的過渡

DevRel領域專家Denis Magda表示&#xff0c;他偶然發現了一篇解釋如何用PostgreSQL無縫替換etcd的文章。該文章指出&#xff0c;Kine項目作為外部etcd端點&#xff0c;可以將Kubernetes etcd請求轉換為底層關系數據庫的SQL查詢。 受到這種方法的啟發&#xff0c;Magda決定進一步…

軟件測試技術之如何編寫測試用例(6)

四、客戶端兼容性測試 1、平臺測試 市場上有很多不同的操作系統類型&#xff0c;最常見的有Windows、Unix、Macintosh、Linux等。Web應用系統的最終用戶究竟使用哪一種操作系統&#xff0c;取決于用戶系統的配置。這樣&#xff0c;就可能會發生兼容性問題&#xff0c;同一個應…

求Win11系統virtualbox+vagrant安裝MacOS虛擬機

文章目錄 一、背景二、素材2.1、virtualboxvagrant 三、問題3.1、安裝失敗3.2、第二個失敗3.3、網絡說 四、求助 一、背景 題主&#xff0c;主要是窮&#xff0c;沒錢買mac筆記本或相關系統的蘋果產品&#xff0c;哈哈&#xff0c;偶爾也有用過MacOS系統&#xff0c;只是還沒有…

actuator/prometheus使用pushgateway上傳jvm監控數據

場景 準備 prometheus已經部署pushgateway服務&#xff0c;訪問{pushgateway.server:9091}可以看到面板 實現 基于springboot引入支持組件&#xff0c;版本可以 <!--監控檢查--><dependency><groupId>org.springframework.boot</groupId><artifa…

H3C交換機如何配置本地端口鏡像并在PC上使用Wireshake抓包

環境: H3C S6520-26Q-SI version 7.1.070, Release 6326 Win 10 專業版 Wireshake Version 4.0.3 問題描述: H3C交換機如何配置本地端口鏡像并在PC上使用Wireshake抓包 解決方案: 配置交換機本地端口鏡像 1.進入系統視圖,并創建本地鏡像組1 <H3C>system-vie…

高效反編譯luac文件

對于游戲開發人員,有時候希望從一些游戲apk中反編譯出源代碼,進行學習,但是如果你觸碰到法律邊緣,那么你要非常小心。 這篇文章,我針對一些用lua寫客戶端或者服務器的編譯過的luac文件進行反編譯,獲取其源代碼的過程。 這里我不贅述如何反編譯解壓apk包的過程了,只說重點…

【【STM32之GPIO】】

STM32之GPIO 學完了正點原子自帶的視頻課之后感覺仍然一知半解現在更新一下來自其他版本的STM32學習 GPIO 就是 General Purpose Input Output 中文名叫通用輸入輸出口 可配置8種輸入輸出模式 引腳電平 0V~3.3V 部分引腳可容忍5V 輸出模式下可控制端口輸出高低電平&#xff…

ubuntu bind dns服務配置

sudo apt-get install bind9 內網搭建DNS服務器&#xff0c;大多數是解析純內網地址使用。但是偶爾也需要解析外網的地址&#xff0c;所以我們可以配置DNS沒有添加A記錄的URL時&#xff0c;forward到外網DNS服務器或者內網的其他DNS服務器解析。 打開配置文件&#xff1a; sud…

Leetcode 動態規劃

動態規劃&#xff1a; 72. Edit Distance class Solution { public:int minDistance(string word1, string word2) {vector<vector<int>> dp(word1.size() 1, vector<int>(word2.size() 1, 0));for (int i 0; i < word1.size(); i) dp[i][0] i;for …

grafana-zabbix基礎操作篇------導入數據源

文章目錄 一、grafana的安裝1.1、下載地址1.2、下載后導入所安裝機器1.3、yum安裝解決依賴1.4、啟動grafana1.5、查看端口是否啟用&#xff08;端口默認3000&#xff09;1.6、瀏覽器訪問 二、添加zabbix數據源2.1、導入數據源 **下一篇 我們講講構建儀表板的操作** 今天&#x…

如何在工作中利用AIGC提質增效?

引言 人工智能技術快速發展&#xff0c;以 ChatGPT 為代表的新的人工智能語言模型的出現與更迭&#xff0c;引發人們極大的興奮和關注。越來越多的企業開始將 AI 技術應用到生產流程&#xff0c;以提高工作效率和生產力。AIGC&#xff08;AI Generated Content&#xff09;是人…

UE4/UE5 照明構建失敗 “Lightmass crashed”解決“數組索引越界”

在構建全局光照時,經常會出現“Lightmass crashed”的錯誤,導致光照構建失敗。本文將分析這一問題的原因,并給出解決建議。 UE4 版本4.26 報錯如下&#xff1a; <None> Lightmass crashed: Assertion failed: (Index > 0) & (Index < ArrayNum) [File:d:\bu…