SpringBoot實(shí)現(xiàn)接口返回?cái)?shù)據(jù)脫敏的代碼示例
引言
在當(dāng)今的信息化時(shí)代,數(shù)據(jù)安全尤為重要。接口返回?cái)?shù)據(jù)脫敏是一種重要的數(shù)據(jù)保護(hù)手段,可以防止敏感信息通過接口返回給客戶端,降低數(shù)據(jù)泄露的風(fēng)險(xiǎn)。本文旨在探討如何在SpringBoot應(yīng)用程序中實(shí)現(xiàn)接口返回?cái)?shù)據(jù)脫敏。我們將介紹一種基于自定義注解結(jié)合Hutool脫敏工具類的方案,以實(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è)過程通常不會(huì)改變數(shù)據(jù)的原始格式,而是通過特定的算法或規(guī)則,將敏感部分替換為特定字符(如星號(hào)*)或者保留部分信息。
1.2 接口數(shù)據(jù)脫敏的重要性
數(shù)據(jù)脫敏的重要性主要體現(xiàn)在以下幾個(gè)方面:
- 保護(hù)用戶隱私: 對(duì)于姓名、身份證號(hào)、手機(jī)號(hào)等個(gè)人敏感信息進(jìn)行脫敏,可以有效保護(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): 通過脫敏處理,即使數(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(面向切面編程):通過切面攔截返回?cái)?shù)據(jù),統(tǒng)一處理敏感字段。這種方式可以集中管理脫敏邏輯,但可能影響性能。
自定義序列化器:利用JSON序列化框架(如Jackson)的自定義序列化器來處理敏感字段。這種方式性能較好,且與業(yè)務(wù)邏輯解耦。
注解+反射:通過自定義注解標(biāo)記需要脫敏的字段,然后利用反射機(jī)制在運(yùn)行時(shí)進(jìn)行脫敏處理。這種方式使用簡(jiǎn)單,易于維護(hù)。
本文將重點(diǎn)介紹如何結(jié)合自定義注解和Hutool工具類來實(shí)現(xiàn)接口數(shù)據(jù)脫敏。
二、開發(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 添加依賴
首先在 pom.xml 文件中添加必要的依賴:
<!-- Hutool工具包 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.25</version>
</dependency>
<!-- Jackson依賴 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.2</version>
</dependency>
3.2 創(chuàng)建自定義注解
接下來,我們創(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 {
/**
* 脫敏類型
*/
DesensitizeType type() default DesensitizeType.DEFAULT;
/**
* 脫敏起始位置
*/
int startInclude() default 0;
/**
* 脫敏結(jié)束位置
*/
int endExclude() default 0;
}
3.3 定義脫敏枚舉類
然后,定義枚舉類 DesensitizeType 來定義字段的脫敏類型:
/**
* 脫敏類型枚舉類
*/
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)建自定義序列化類
Hutool支持的脫敏數(shù)據(jù)類型包括:
- 用戶id
- 中文姓名
- 身份證號(hào)
- 座機(jī)號(hào)
- 手機(jī)號(hào)
- 地址
- 電子郵件
- 密碼
- 中國(guó)大陸車牌,包含普通車輛、新能源車輛
- 銀行卡
整體來說,所謂脫敏就是隱藏掉信息中的一部分關(guān)鍵信息,用*代替。大家可以自己看一看DesensitizedUtil類中方法,其實(shí)就是replace方法和hide方法的使用,想要自定義規(guī)則進(jìn)行隱藏可以仿照進(jìn)行實(shí)現(xiàn)。
/**
* 脫敏序列化器,用于在序列化字符串時(shí)根據(jù)不同的脫敏類型進(jìn)行數(shù)據(jù)脫敏。
*
* @author shijun
* @date 2024/07/08
*/
public class DesensitizeSerializer extends JsonSerializer<String> implements ContextualSerializer {
/**
* 脫敏類型,默認(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ù)脫敏類型對(duì)字符串進(jìn)行相應(yīng)的脫敏處理。
*
* @param value 待序列化的字符串
* @param gen JSON生成器,用于寫入處理后的字符串
* @param serializers 序列化器提供者,用于獲取其他序列化器
* @throws IOException 如果序列化過程中發(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)前屬性的信息,用于獲取注解和屬性類型
* @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ù)脫敏類型對(duì)字符串進(jìn)行相應(yīng)的脫敏處理。根據(jù)不同的脫敏類型,使用不同的處理方法對(duì)字符串進(jìn)行脫敏,并將處理后的字符串寫入JSON生成器中。
- createContextual方法根據(jù)上下文信息創(chuàng)建自定義的序列化器,用于處理帶有@Desensitize注解的屬性。它通過獲取注解中的脫敏類型和自定義規(guī)則的起始位置和結(jié)束位置,對(duì)實(shí)例進(jìn)行相應(yīng)的設(shè)置,并返回自定義的序列化器實(shí)例。
這個(gè)序列化器的主要用途是在 JSON 序列化過程中自動(dòng)對(duì)標(biāo)記了 @Desensitize 注解的字段進(jìn)行脫敏處理。
四、測(cè)試
4.1 編寫測(cè)試代碼
- 編寫實(shí)體類
@Data
public class UserDTO {
/**
* 用戶姓名
*/
@Desensitize(type = DesensitizeType.CHINESE_NAME)
private String name;
/**
* 用戶手機(jī)號(hào)
*/
@Desensitize(type = DesensitizeType.PHONE)
private String phoneNumber;
/**
* 用戶電子郵件地址
*/
@Desensitize(type = DesensitizeType.EMAIL)
private String email;
/**
* 用戶密碼
*/
@Desensitize(type = DesensitizeType.PASSWORD)
private String password;
/**
* 用戶身份證號(hào)碼
*/
@Desensitize(type = DesensitizeType.ID_CARD)
private String idCard;
/**
* 用戶銀行卡號(hào)
*/
@Desensitize(type = DesensitizeType.BANK_CARD)
private String bankCard;
/**
* 用戶地址
*/
@Desensitize(type = DesensitizeType.ADDRESS)
private String address;
/**
* 游戲名稱
*/
@Desensitize(type = DesensitizeType.CUSTOM_RULE, startInclude = 2, endExclude = 6)
private String gameName;
}
- 編寫測(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("遼寧省盤錦市興隆臺(tái)區(qū)紅村鄉(xiāng)441號(hào)");
userDTO.setIdCard("447465200912089605");
userDTO.setBankCard("6217000000000000000");
userDTO.setGameName("超級(jí)無敵大鐵錘");
return userDTO;
}
}
4.2 測(cè)試

五、總結(jié)
在本文中,我們探討了在SpringBoot應(yīng)用程序中實(shí)現(xiàn)數(shù)據(jù)脫敏的重要性,并提出了通過自定義注解結(jié)合Hutool脫敏工具類實(shí)現(xiàn)數(shù)據(jù)脫敏的解決方案。通過這個(gè)方案,我們能夠有效地對(duì)敏感數(shù)據(jù)進(jìn)行脫敏處理,從而保護(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)文章!
相關(guān)文章
詳解Java如何在CompletableFuture中實(shí)現(xiàn)日志記錄
這篇文章主要為大家詳細(xì)介紹了一種slf4j自帶的MDC類,來記錄完整的請(qǐng)求日志,和在CompletableFuture異步線程中如何保留鏈路id,需要的可以參考一下2023-04-04
項(xiàng)目依賴Springboot jar失敗解決方案
這篇文章主要介紹了項(xiàng)目依賴Springboot jar失敗解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
Java 實(shí)戰(zhàn)范例之線上婚紗攝影預(yù)定系統(tǒng)的實(shí)現(xiàn)
讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+javaweb+SSM+springboot+mysql實(shí)現(xiàn)一個(gè)線上婚紗攝影預(yù)定系統(tǒng),大家可以在過程中查缺補(bǔ)漏,提升水平2021-11-11
mybatis plus開發(fā)過程中遇到的問題記錄及解決
這篇文章主要介紹了mybatis plus開發(fā)過程中遇到的問題記錄及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
讀取Java文件到byte數(shù)組的三種方法(總結(jié))
下面小編就為大家?guī)硪黄x取Java文件到byte數(shù)組的三種方法(總結(jié))。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-08-08

