SpringBoot實(shí)現(xiàn)接口返回?cái)?shù)據(jù)脫敏的代碼示例
引言
在當(dāng)今的信息化時(shí)代,數(shù)據(jù)安全尤為重要。接口返回?cái)?shù)據(jù)脫敏是一種重要的數(shù)據(jù)保護(hù)手段,可以防止敏感信息通過(guò)接口返回給客戶(hù)端,降低數(shù)據(jù)泄露的風(fēng)險(xiǎn)。本文旨在探討如何在SpringBoot應(yīng)用程序中實(shí)現(xiàn)接口返回?cái)?shù)據(jù)脫敏。我們將介紹一種基于自定義注解結(jié)合Hutool脫敏工具類(lèi)的方案,以實(shí)現(xiàn)SpringBoot中的接口返回?cái)?shù)據(jù)脫敏。
一、接口數(shù)據(jù)脫敏概述
1.1 接口數(shù)據(jù)脫敏的定義
接口數(shù)據(jù)脫敏是指在Web應(yīng)用程序的API接口返回?cái)?shù)據(jù)時(shí),對(duì)包含敏感信息的字段進(jìn)行處理,使其部分或全部信息被隱藏或替換,以防止敏感信息的泄露。這個(gè)過(guò)程通常不會(huì)改變數(shù)據(jù)的原始格式,而是通過(guò)特定的算法或規(guī)則,將敏感部分替換為特定字符(如星號(hào)*)或者保留部分信息。
1.2 接口數(shù)據(jù)脫敏的重要性
數(shù)據(jù)脫敏的重要性主要體現(xiàn)在以下幾個(gè)方面:
- 保護(hù)用戶(hù)隱私: 對(duì)于姓名、身份證號(hào)、手機(jī)號(hào)等個(gè)人敏感信息進(jìn)行脫敏,可以有效保護(hù)用戶(hù)隱私,防止信息被濫用。
- 遵守法律法規(guī): 許多國(guó)家和地區(qū)都制定了嚴(yán)格的數(shù)據(jù)保護(hù)法規(guī),如歐盟的GDPR和中國(guó)的《個(gè)人信息保護(hù)法》。實(shí)施數(shù)據(jù)脫敏有助于企業(yè)合規(guī)經(jīng)營(yíng)。
- 降低安全風(fēng)險(xiǎn): 通過(guò)脫敏處理,即使數(shù)據(jù)不慎泄露,也能最大限度地減少敏感信息被盜用的風(fēng)險(xiǎn)。
- 支持?jǐn)?shù)據(jù)共享: 在保護(hù)隱私的同時(shí),脫敏數(shù)據(jù)仍然保留了一定的分析價(jià)值,有利于數(shù)據(jù)的安全共享和利用。
1.3 接口數(shù)據(jù)脫敏的實(shí)現(xiàn)方式
手動(dòng)脫敏:在業(yè)務(wù)邏輯層直接對(duì)敏感數(shù)據(jù)進(jìn)行處理。這種方式靈活但容易遺漏,且代碼重復(fù)率高。
AOP(面向切面編程):通過(guò)切面攔截返回?cái)?shù)據(jù),統(tǒng)一處理敏感字段。這種方式可以集中管理脫敏邏輯,但可能影響性能。
自定義序列化器:利用JSON序列化框架(如Jackson)的自定義序列化器來(lái)處理敏感字段。這種方式性能較好,且與業(yè)務(wù)邏輯解耦。
注解+反射:通過(guò)自定義注解標(biāo)記需要脫敏的字段,然后利用反射機(jī)制在運(yùn)行時(shí)進(jìn)行脫敏處理。這種方式使用簡(jiǎn)單,易于維護(hù)。
本文將重點(diǎn)介紹如何結(jié)合自定義注解和Hutool工具類(lèi)來(lái)實(shí)現(xiàn)接口數(shù)據(jù)脫敏。
二、開(kāi)發(fā)環(huán)境
- JDK版本:JDK 17
- Spring Boot版本:Spring Boot 3.2.2
- 構(gòu)建工具:Maven
三、實(shí)現(xiàn)接口返回?cái)?shù)據(jù)脫敏
3.1 添加依賴(lài)
首先在 pom.xml 文件中添加必要的依賴(lài):
<!-- Hutool工具包 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.25</version>
</dependency>
<!-- Jackson依賴(lài) -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.2</version>
</dependency>
3.2 創(chuàng)建自定義注解
接下來(lái),我們創(chuàng)建一個(gè)自定義注解 @Desensitize:
/**
* 用于標(biāo)記字段需要進(jìn)行脫敏處理的注解
*
* @author shijun
* @date 2024/07/09
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = DesensitizeSerializer.class)
public @interface Desensitize {
/**
* 脫敏類(lèi)型
*/
DesensitizeType type() default DesensitizeType.DEFAULT;
/**
* 脫敏起始位置
*/
int startInclude() default 0;
/**
* 脫敏結(jié)束位置
*/
int endExclude() default 0;
}
3.3 定義脫敏枚舉類(lèi)
然后,定義枚舉類(lèi) DesensitizeType 來(lái)定義字段的脫敏類(lèi)型:
/**
* 脫敏類(lèi)型枚舉類(lèi)
*/
public enum DesensitizeType {
/**
* 默認(rèn)脫敏
*/
DEFAULT,
/**
* 自定義脫敏
*/
CUSTOM_RULE,
/**
* 手機(jī)號(hào)脫敏
*/
PHONE,
/**
* 電子郵件脫敏
*/
EMAIL,
/**
* 身份證號(hào)脫敏
*/
ID_CARD,
/**
* 銀行卡號(hào)脫敏
*/
BANK_CARD,
/**
* 地址脫敏
*/
ADDRESS,
/**
* 中文姓名脫敏
*/
CHINESE_NAME,
/**
* 密碼脫敏
*/
PASSWORD,
}
3.4 創(chuàng)建自定義序列化類(lèi)
Hutool支持的脫敏數(shù)據(jù)類(lèi)型包括:
- 用戶(hù)id
- 中文姓名
- 身份證號(hào)
- 座機(jī)號(hào)
- 手機(jī)號(hào)
- 地址
- 電子郵件
- 密碼
- 中國(guó)大陸車(chē)牌,包含普通車(chē)輛、新能源車(chē)輛
- 銀行卡
整體來(lái)說(shuō),所謂脫敏就是隱藏掉信息中的一部分關(guān)鍵信息,用*代替。大家可以自己看一看DesensitizedUtil類(lèi)中方法,其實(shí)就是replace方法和hide方法的使用,想要自定義規(guī)則進(jìn)行隱藏可以仿照進(jìn)行實(shí)現(xiàn)。
/**
* 脫敏序列化器,用于在序列化字符串時(shí)根據(jù)不同的脫敏類(lèi)型進(jìn)行數(shù)據(jù)脫敏。
*
* @author shijun
* @date 2024/07/08
*/
public class DesensitizeSerializer extends JsonSerializer<String> implements ContextualSerializer {
/**
* 脫敏類(lèi)型,默認(rèn)為DEFAULT
*/
private DesensitizeType type;
/**
* 脫敏起始位置
*/
private int startInclude;
/**
* 脫敏結(jié)束位置
*/
private int endExclude;
public DesensitizeSerializer() {
this.type = DesensitizeType.DEFAULT;
}
public DesensitizeSerializer(DesensitizeType type) {
this.type = type;
}
/**
* 序列化字符串時(shí)調(diào)用,根據(jù)脫敏類(lèi)型對(duì)字符串進(jìn)行相應(yīng)的脫敏處理。
*
* @param value 待序列化的字符串
* @param gen JSON生成器,用于寫(xiě)入處理后的字符串
* @param serializers 序列化器提供者,用于獲取其他序列化器
* @throws IOException 如果序列化過(guò)程中發(fā)生I/O錯(cuò)誤
*/
@Override
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
switch (type) {
case CUSTOM_RULE:
// 這里是對(duì)字符串的startInclude到endExclude字段進(jìn)行隱藏處理,如果想要實(shí)現(xiàn)兩端保留,可以考慮使用StrUtil的replace方法
gen.writeString(StrUtil.hide(value, startInclude, endExclude));
break;
case PHONE:
gen.writeString(DesensitizedUtil.mobilePhone(value));
break;
case EMAIL:
gen.writeString(DesensitizedUtil.email(value));
break;
case ID_CARD:
gen.writeString(DesensitizedUtil.idCardNum(value, 1, 2));
break;
case BANK_CARD:
gen.writeString(DesensitizedUtil.bankCard(value));
break;
case ADDRESS:
gen.writeString(DesensitizedUtil.address(value, 8));
break;
case CHINESE_NAME:
gen.writeString(DesensitizedUtil.chineseName(value));
break;
case PASSWORD:
gen.writeString(DesensitizedUtil.password(value));
break;
default:
gen.writeString(value);
break;
}
}
/**
* 根據(jù)上下文信息創(chuàng)建自定義的序列化器,用于處理帶有@Desensitize注解的屬性。
*
* @param prov 序列化器提供者,用于獲取其他序列化器
* @param property 當(dāng)前屬性的信息,用于獲取注解和屬性類(lèi)型
* @return 自定義的序列化器實(shí)例
*/
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) {
if (property != null) {
Desensitize annotation = property.getAnnotation(Desensitize.class);
if (annotation != null) {
this.type = annotation.type();
if (annotation.type() == DesensitizeType.CUSTOM_RULE) {
this.startInclude = annotation.startInclude();
this.endExclude = annotation.endExclude();
}
}
}
return this;
}
}
代碼分析:
- serialize方法在序列化字符串時(shí)被調(diào)用,根據(jù)脫敏類(lèi)型對(duì)字符串進(jìn)行相應(yīng)的脫敏處理。根據(jù)不同的脫敏類(lèi)型,使用不同的處理方法對(duì)字符串進(jìn)行脫敏,并將處理后的字符串寫(xiě)入JSON生成器中。
- createContextual方法根據(jù)上下文信息創(chuàng)建自定義的序列化器,用于處理帶有@Desensitize注解的屬性。它通過(guò)獲取注解中的脫敏類(lèi)型和自定義規(guī)則的起始位置和結(jié)束位置,對(duì)實(shí)例進(jìn)行相應(yīng)的設(shè)置,并返回自定義的序列化器實(shí)例。
這個(gè)序列化器的主要用途是在 JSON 序列化過(guò)程中自動(dòng)對(duì)標(biāo)記了 @Desensitize 注解的字段進(jìn)行脫敏處理。
四、測(cè)試
4.1 編寫(xiě)測(cè)試代碼
- 編寫(xiě)實(shí)體類(lèi)
@Data
public class UserDTO {
/**
* 用戶(hù)姓名
*/
@Desensitize(type = DesensitizeType.CHINESE_NAME)
private String name;
/**
* 用戶(hù)手機(jī)號(hào)
*/
@Desensitize(type = DesensitizeType.PHONE)
private String phoneNumber;
/**
* 用戶(hù)電子郵件地址
*/
@Desensitize(type = DesensitizeType.EMAIL)
private String email;
/**
* 用戶(hù)密碼
*/
@Desensitize(type = DesensitizeType.PASSWORD)
private String password;
/**
* 用戶(hù)身份證號(hào)碼
*/
@Desensitize(type = DesensitizeType.ID_CARD)
private String idCard;
/**
* 用戶(hù)銀行卡號(hào)
*/
@Desensitize(type = DesensitizeType.BANK_CARD)
private String bankCard;
/**
* 用戶(hù)地址
*/
@Desensitize(type = DesensitizeType.ADDRESS)
private String address;
/**
* 游戲名稱(chēng)
*/
@Desensitize(type = DesensitizeType.CUSTOM_RULE, startInclude = 2, endExclude = 6)
private String gameName;
}
- 編寫(xiě)測(cè)試接口
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("/desensitize")
public UserDTO getUser() {
UserDTO userDTO = new UserDTO();
userDTO.setName("孫大圣");
userDTO.setEmail("shijun@163.com");
userDTO.setPhoneNumber("12345678901");
userDTO.setPassword("123456");
userDTO.setAddress("遼寧省盤(pán)錦市興隆臺(tái)區(qū)紅村鄉(xiāng)441號(hào)");
userDTO.setIdCard("447465200912089605");
userDTO.setBankCard("6217000000000000000");
userDTO.setGameName("超級(jí)無(wú)敵大鐵錘");
return userDTO;
}
}
4.2 測(cè)試

五、總結(jié)
在本文中,我們探討了在SpringBoot應(yīng)用程序中實(shí)現(xiàn)數(shù)據(jù)脫敏的重要性,并提出了通過(guò)自定義注解結(jié)合Hutool脫敏工具類(lèi)實(shí)現(xiàn)數(shù)據(jù)脫敏的解決方案。通過(guò)這個(gè)方案,我們能夠有效地對(duì)敏感數(shù)據(jù)進(jìn)行脫敏處理,從而保護(hù)用戶(hù)隱私和數(shù)據(jù)安全,希望對(duì)大家有所幫助。
以上就是SpringBoot實(shí)現(xiàn)接口返回?cái)?shù)據(jù)脫敏的代碼示例的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot接口數(shù)據(jù)脫敏的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Springboot敏感字段脫敏的實(shí)現(xiàn)思路
- SpringBoot?自定義注解之脫敏注解詳解
- SpringBoot使用jasypt實(shí)現(xiàn)數(shù)據(jù)庫(kù)信息脫敏的方法詳解
- Springboot+Hutool自定義注解實(shí)現(xiàn)數(shù)據(jù)脫敏
- SpringBoot實(shí)現(xiàn)返回值數(shù)據(jù)脫敏的步驟詳解
- 淺析如何在SpringBoot中實(shí)現(xiàn)數(shù)據(jù)脫敏
- SpringBoot利用自定義注解實(shí)現(xiàn)隱私數(shù)據(jù)脫敏(加密顯示)的解決方案
- SpringBoot數(shù)據(jù)脫敏的實(shí)現(xiàn)示例
- SpringBoot實(shí)現(xiàn)數(shù)據(jù)加密脫敏的示例代碼
- SpringBoot敏感數(shù)據(jù)脫敏的處理方式
- SpringBoot常用脫敏方案小結(jié)
相關(guān)文章
解決JDK9以上的非法反射訪(fǎng)問(wèn)警告的問(wèn)題
文章介紹了在JDK9及以上版本中,由于模塊系統(tǒng)限制,舊版庫(kù)(如protostuff)會(huì)出現(xiàn)非法反射訪(fǎng)問(wèn)的警告,解決方法是使用--illegal-access參數(shù),并通過(guò)--add-opens參數(shù)允許特定模塊的非法反射訪(fǎng)問(wèn),文章還提供了在IDEA和構(gòu)建工具(Maven和Gradle)中配置這些參數(shù)的示例2025-11-11
Idea運(yùn)行單個(gè)main方法,不編譯整個(gè)工程的問(wèn)題
這篇文章主要介紹了Idea運(yùn)行單個(gè)main方法,不編譯整個(gè)工程的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
java實(shí)現(xiàn)簡(jiǎn)易飛機(jī)大戰(zhàn)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)易飛機(jī)大戰(zhàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
MyBatis-Plus攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限控制的方法
MyBatis-Plus是一款基于MyBatis的增強(qiáng)工具,它提供了一些便捷的功能和增強(qiáng)的查詢(xún)能力,數(shù)據(jù)權(quán)限控制是在系統(tǒng)中對(duì)用戶(hù)訪(fǎng)問(wèn)數(shù)據(jù)進(jìn)行限制的一種機(jī)制,這篇文章主要給大家介紹了關(guān)于MyBatis-Plus攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限控制的相關(guān)資料,需要的朋友可以參考下2024-01-01
SpringMVC中@RequestMapping注解用法實(shí)例
通過(guò)@RequestMapping注解可以定義不同的處理器映射規(guī)則,下面這篇文章主要給大家介紹了關(guān)于SpringMVC中@RequestMapping注解用法的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06
Java基于fork/koin類(lèi)實(shí)現(xiàn)并發(fā)排序
這篇文章主要介紹了Java基于fork/koin類(lèi)實(shí)現(xiàn)并發(fā)排序,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02
Spring Boot整合Mybatis Plus和Swagger2的教程詳解
這篇文章主要介紹了Spring Boot整合Mybatis Plus和Swagger2的教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02

