最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot對敏感數(shù)據(jù)進行脫敏的全過程

 更新時間:2026年04月26日 15:17:39   作者:希望永不加班  
在項目開發(fā)中,數(shù)據(jù)庫經(jīng)常會存儲大量用戶敏感信息,例如手機號、身份證號、郵箱、銀行卡號、家庭地址、姓名等數(shù)據(jù),如果后端直接把原始數(shù)據(jù)返回給前端,會造成嚴(yán)重的用戶隱私泄露問題,所以本文給大家介紹了SpringBoot對敏感數(shù)據(jù)進行脫敏的全過程,需要的朋友可以參考下

引言

在項目開發(fā)中,數(shù)據(jù)庫經(jīng)常會存儲大量用戶敏感信息,例如手機號、身份證號、郵箱、銀行卡號、家庭地址、姓名等數(shù)據(jù)。如果后端直接把原始數(shù)據(jù)返回給前端,一旦接口被抓包、日志泄露、數(shù)據(jù)庫泄露,就會造成嚴(yán)重的用戶隱私泄露問題,違反數(shù)據(jù)安全規(guī)范。

因此企業(yè)項目普遍需要做數(shù)據(jù)脫敏,也就是在不修改原始數(shù)據(jù)庫數(shù)據(jù)的前提下,對返回字段進行掩碼處理,隱藏部分字符,只展示明文部分。

一、脫敏方案對比

目前常見的數(shù)據(jù)脫敏實現(xiàn)方式有 4 種,各有優(yōu)劣:

1. 工具類手動脫敏
業(yè)務(wù)代碼中手動調(diào)用工具處理,侵入性極強,每個字段都要處理,冗余代碼多。

2. AOP切面脫敏
攔截返回結(jié)果統(tǒng)一處理,缺點是解析整個返回體 JSON,性能較差,復(fù)雜對象嵌套難以精準(zhǔn)控制。

3. MyBatis 層脫敏
SQL查詢、結(jié)果集映射時處理,只針對數(shù)據(jù)庫查詢有效,其他接口返回?zé)o法統(tǒng)一處理。

4. Jackson 序列化層脫敏(本文方案)
最優(yōu)方案。基于 Jackson 自定義序列化器,在實體類字段上加注解即可生效,僅在對象轉(zhuǎn) JSON 階段脫敏,業(yè)務(wù)零侵入、性能高、靈活可控、支持嵌套對象、全局統(tǒng)一,也是目前企業(yè)項目主流標(biāo)準(zhǔn)方案。

二、脫敏核心原理

SpringBoot 默認(rèn)使用 Jackson 完成 Java 對象轉(zhuǎn) JSON 字符串返回前端。
我們自定義 JsonSerializer 序列化器,實現(xiàn)自定義脫敏邏輯,再封裝通用注解標(biāo)注在實體類敏感字段上。

流程:

1. 后端查詢數(shù)據(jù)庫,得到完整原始實體對象

2. 接口返回對象,Jackson 開始序列化

3. 檢測字段上的脫敏注解

4. 執(zhí)行對應(yīng)脫敏序列化器,對數(shù)據(jù)進行掩碼替換

5. 前端最終拿到脫敏后的 JSON 數(shù)據(jù),原始數(shù)據(jù)全程不暴露

優(yōu)勢:原始數(shù)據(jù)庫數(shù)據(jù)完全不變,僅返回時脫敏,不影響入庫、不影響業(yè)務(wù)邏輯。

三、環(huán)境準(zhǔn)備

1. Maven 依賴

SpringBoot Web 自帶 Jackson,無需額外引入依賴,僅需基礎(chǔ) Web、Lombok 即可。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.18</version>
        <relativePath/>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>springboot-desensitization</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-desensitization</name>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!-- Web 核心 內(nèi)置Jackson序列化 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

2. application.yml

無需額外復(fù)雜配置,開箱即用

server:
  port: 8080

四、統(tǒng)一返回結(jié)果類

沿用本專欄所有文章統(tǒng)一 Result 返回體,格式完全一致。

import lombok.Data;
@Data
public class Result<T> {
    private int code;
    private String msg;
    private T data;
    public static <T> Result<T> success(T data) {
        Result<T> result = new Result<>();
        result.setCode(200);
        result.setMsg("操作成功");
        result.setData(data);
        return result;
    }
    public static <T> Result<T> error(String msg) {
        Result<T> result = new Result<>();
        result.setCode(500);
        result.setMsg(msg);
        return result;
    }
}

五、脫敏類型枚舉

統(tǒng)一定義所有常用脫敏類型,擴展方便,規(guī)范統(tǒng)一。
包含:手機號、身份證、郵箱、銀行卡、姓名、地址。

/**
 * 敏感數(shù)據(jù)脫敏類型枚舉
 */
public enum DesensitizeType {
    /**
     * 默認(rèn)不處理
     */
    DEFAULT,
    /**
     * 手機號 11位
     * 138****1234
     */
    PHONE,
    /**
     * 18位身份證
     * 320123********1234
     */
    ID_CARD,
    /**
     * 郵箱
     * test****@qq.com
     */
    EMAIL,
    /**
     * 銀行卡號
     * 6222****1234
     */
    BANK_CARD,
    /**
     * 中文姓名
     * 張**
     */
    NAME,
    /**
     * 詳細(xì)地址
     * 廣東省深圳市南山區(qū)****
     */
    ADDRESS
}

六、脫敏工具類

封裝所有類型脫敏算法,抽取公共工具方法,統(tǒng)一掩碼替換規(guī)則。

import org.springframework.util.StringUtils;
/**
 * 敏感數(shù)據(jù)脫敏工具類
 */
public class DesensitizeUtil {
    /**
     * 通用掩碼截取方法
     * @param str 原始字符串
     * @param start 前面保留位數(shù)
     * @param end 后面保留位數(shù)
     * @return 脫敏后字符串
     */
    public static String mask(String str, int start, int end) {
        if (StringUtils.isEmpty(str)) {
            return str;
        }
        int len = str.length();
        // 長度不足直接返回原數(shù)據(jù)
        if (len <= start + end) {
            return str;
        }
        // 截取前綴 + 中間星號 + 截取后綴
        String prefix = str.substring(0, start);
        String suffix = str.substring(len - end);
        return prefix + "****" + suffix;
    }
    // ==================== 各類敏感數(shù)據(jù)脫敏實現(xiàn) ====================
    /**
     * 手機號脫敏 11位
     */
    public static String phone(String phone) {
        return mask(phone, 3, 4);
    }
    /**
     * 身份證18位脫敏
     */
    public static String idCard(String idCard) {
        return mask(idCard, 6, 4);
    }
    /**
     * 郵箱脫敏
     */
    public static String email(String email) {
        if (StringUtils.isEmpty(email) || !email.contains("@")) {
            return email;
        }
        int index = email.indexOf("@");
        String prefix = email.substring(0, index);
        String suffix = email.substring(index);
        // 用戶名部分脫敏
        String pre = prefix.length() > 2 ? prefix.substring(0, 2) : prefix;
        return pre + "****" + suffix;
    }
    /**
     * 銀行卡脫敏
     */
    public static String bankCard(String card) {
        return mask(card, 4, 4);
    }
    /**
     * 中文姓名脫敏
     */
    public static String name(String name) {
        if (StringUtils.isEmpty(name) || name.length() <= 1) {
            return name;
        }
        return name.charAt(0) + "**";
    }
    /**
     * 詳細(xì)地址脫敏
     */
    public static String address(String address) {
        if (StringUtils.isEmpty(address) || address.length() <= 8) {
            return address;
        }
        return address.substring(0, 8) + "****";
    }
}

七、自定義脫敏注解

封裝通用注解,標(biāo)注在實體類字段上,指定脫敏類型,無侵入式。

import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.lang.annotation.*;
/**
 * 自定義敏感字段脫敏注解
 * 標(biāo)注在實體類字段上,序列化自動脫敏
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@JacksonAnnotationsInside
@JsonSerialize(using = DesensitizeSerializer.class)
public @interface Desensitize {
    /**
     * 脫敏類型
     */
    DesensitizeType value();
}

八、自定義Jackson序列化器

實現(xiàn) JsonSerializer,在序列化階段根據(jù)注解類型,調(diào)用對應(yīng)脫敏方法。
整個方案核心代碼,Spring 會自動在對象轉(zhuǎn)JSON時執(zhí)行。

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;
import java.io.IOException;
/**
 * 自定義脫敏序列化器
 * Jackson 序列化層統(tǒng)一處理
 */
public class DesensitizeSerializer extends StdScalarSerializer<String> {
    public DesensitizeSerializer() {
        super(String.class);
    }
    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        // 獲取字段上的脫敏注解
        Desensitize annotation = gen.getAnnotation(Desensitize.class);
        if (annotation == null) {
            gen.writeString(value);
            return;
        }
        DesensitizeType type = annotation.value();
        String result = value;
        // 根據(jù)類型執(zhí)行對應(yīng)脫敏算法
        switch (type) {
            case PHONE:
                result = DesensitizeUtil.phone(value);
                break;
            case ID_CARD:
                result = DesensitizeUtil.idCard(value);
                break;
            case EMAIL:
                result = DesensitizeUtil.email(value);
                break;
            case BANK_CARD:
                result = DesensitizeUtil.bankCard(value);
                break;
            case NAME:
                result = DesensitizeUtil.name(value);
                break;
            case ADDRESS:
                result = DesensitizeUtil.address(value);
                break;
            default:
                break;
        }
        // 寫入脫敏后數(shù)據(jù)
        gen.writeString(result);
    }
}

九、用戶實體類測試

直接在敏感字段加上 @Desensitize(xxx) 注解即可,無需修改任何業(yè)務(wù)代碼。

import lombok.Data;
import java.io.Serializable;
@Data
public class User implements Serializable {
    private Long id;
    private String username;
    // 姓名脫敏
    @Desensitize(DesensitizeType.NAME)
    private String realName;
    // 手機號脫敏
    @Desensitize(DesensitizeType.PHONE)
    private String phone;
    // 身份證脫敏
    @Desensitize(DesensitizeType.ID_CARD)
    private String idCard;
    // 郵箱脫敏
    @Desensitize(DesensitizeType.EMAIL)
    private String email;
    // 銀行卡脫敏
    @Desensitize(DesensitizeType.BANK_CARD)
    private String bankCard;
    // 詳細(xì)地址脫敏
    @Desensitize(DesensitizeType.ADDRESS)
    private String address;
}

十、測試接口

模擬數(shù)據(jù)庫查詢完整數(shù)據(jù),直接返回對象,由 Jackson 序列化自動完成脫敏。

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
@RestController
@RequestMapping("/user")
public class UserController {
    @GetMapping("/info")
    public Result<User> getUserInfo() {
        // 模擬數(shù)據(jù)庫完整原始敏感數(shù)據(jù)
        User user = new User();
        user.setId(1L);
        user.setUsername("admin");
        user.setRealName("張三三");
        user.setPhone("13812345678");
        user.setIdCard("320123199801011234");
        user.setEmail("zhangsan@163.com");
        user.setBankCard("6222021234567891234");
        user.setAddress("廣東省深圳市南山區(qū)科技園高新園區(qū)1棟");
        return Result.success(user);
    }
}

十一、運行測試效果

啟動項目訪問接口:

http://localhost:8080/user/info

前端返回 JSON 全部自動脫敏,效果如下:

{
  "code": 200,
  "msg": "操作成功",
  "data": {
    "id": 1,
    "username": "admin",
    "realName": "張**",
    "phone": "138****5678",
    "idCard": "320123********1234",
    "email": "zh****@163.com",
    "bankCard": "6222****1234",
    "address": "廣東省深圳市南山區(qū)****"
  }
}

數(shù)據(jù)庫原始數(shù)據(jù)完全不變,僅接口返回序列化階段脫敏。

十二、擴展增強:嵌套對象脫敏

該方案天然支持實體類嵌套對象脫敏,內(nèi)部字段注解依然生效,無需額外配置。

@Data
class UserInfo {
    @Desensitize(DesensitizeType.PHONE)
    private String phone;
}

十三、生產(chǎn)環(huán)境擴展優(yōu)化

1. 動態(tài)自定義脫敏規(guī)則

支持注解自定義前后保留位數(shù),無需新增枚舉,靈活適配各種不規(guī)則字段。

@Desensitize(type = CUSTOM, start = 2, end = 3)

2. 全局配置區(qū)分環(huán)境脫敏

開發(fā)、測試環(huán)境不脫敏(方便調(diào)試),生產(chǎn)環(huán)境自動脫敏,通過配置文件開關(guān)控制。

desensitize:
  enable: true # 全局脫敏總開關(guān)

3. 排除指定接口脫敏

部分后臺管理接口、管理員接口需要查看完整原始數(shù)據(jù),配置放行不脫敏。

4. 結(jié)合日志脫敏

擴展實現(xiàn)日志打印脫敏,防止日志打印泄露用戶隱私。

5. 空值、null值兼容處理

完善序列化器空值判斷,避免空指針異常。

十四、方案優(yōu)勢總結(jié)

1. 業(yè)務(wù)零侵入:僅實體字段加注解,Controller、Service、DAO 全部無需改動

2. 性能極高:基于 Jackson 原生序列化,無額外反射、無JSON二次解析

3. 統(tǒng)一可控:所有接口返回統(tǒng)一處理,一處配置全局生效

4. 擴展方便:新增脫敏類型只需要加枚舉+工具方法,無需改動核心序列化器

5. 兼容所有返回:單對象、List集合、嵌套對象、Result包裝體全部支持

6. 數(shù)據(jù)安全:原始庫數(shù)據(jù)不變,僅對外返回掩碼數(shù)據(jù),滿足等保合規(guī)要求

十五、常見問題

1. 注解不生效
原因:字段是 static 修飾、字段無get方法、Lombok版本過低;
解決:去掉static,保證Lombok正常生成getter。

2. 返回null不脫敏
工具類已做空值判斷,直接返回null,不會報錯。

3. 集合、List返回不生效
Jackson 序列化天然支持集合遍歷序列化,完全生效無需額外處理。

4. 自定義序列化與全局Jackson配置沖突
使用 @JacksonAnnotationsInside 注解整合,不會沖突。

以上就是SpringBoot對敏感數(shù)據(jù)進行脫敏的全過程的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot敏感數(shù)據(jù)進行脫敏的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解java代碼中init method和destroy method的三種使用方式

    詳解java代碼中init method和destroy method的三種使用方式

    這篇文章主要介紹了詳解java代碼中init method和destroy method的三種使用方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • ElasticSearch突然采集不到日志問題解決分析

    ElasticSearch突然采集不到日志問題解決分析

    這篇文章主要為大家介紹了ElasticSearch突然采集不到日志問題解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-04-04
  • 解決springboot項目打成jar包后運行時碰到的小坑

    解決springboot項目打成jar包后運行時碰到的小坑

    這篇文章主要介紹了解決springboot項目打成jar包后運行時碰到的小坑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • MyBatis-Plus批量操作SQL日志不打印問題的解決方案

    MyBatis-Plus批量操作SQL日志不打印問題的解決方案

    在使用 MyBatis-Plus 的?saveBatch()?和?updateBatchById()?方法進行批量數(shù)據(jù)操作時,發(fā)現(xiàn)自定義的 Druid SQL 日志攔截器無法打印這些批量操作的 SQL 語句,導(dǎo)致調(diào)試和問題排查困難,本文給大家該問題的詳細(xì)解決方案,需要的朋友可以參考下
    2026-03-03
  • springboot @RequestBody 接收字符串實例

    springboot @RequestBody 接收字符串實例

    這篇文章主要介紹了springboot @RequestBody 接收字符串實例,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Java7和Java8中的ConcurrentHashMap原理解析

    Java7和Java8中的ConcurrentHashMap原理解析

    這篇文章主要介紹了Java7和Java8中的ConcurrentHashMap原理解析,對ConcurrentHashMap感興趣的讀者,一定要好好看一下
    2021-04-04
  • Spring MVC的國際化實現(xiàn)代碼

    Spring MVC的國際化實現(xiàn)代碼

    本篇文章主要介紹了Spring MVC的國際化實現(xiàn)代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • java實現(xiàn)簡單的汽車租賃系統(tǒng)

    java實現(xiàn)簡單的汽車租賃系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)簡單的汽車租賃系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 下載遠(yuǎn)程maven倉庫的jar?手動放到本地倉庫詳細(xì)操作

    下載遠(yuǎn)程maven倉庫的jar?手動放到本地倉庫詳細(xì)操作

    這篇文章主要介紹了如何下載遠(yuǎn)程maven倉庫的jar?手動放到本地倉庫,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-03-03
  • 使用curator實現(xiàn)zookeeper鎖服務(wù)的示例分享

    使用curator實現(xiàn)zookeeper鎖服務(wù)的示例分享

    這篇文章主要介紹了使用curator實現(xiàn)zookeeper鎖服務(wù)的示例,需要的朋友可以參考下
    2014-02-02

最新評論

天等县| 黔西| 乐陵市| 娄底市| 宁明县| 巴东县| 富民县| 衢州市| 腾冲县| 承德市| 手游| 江门市| 兰坪| 大同县| 博兴县| 登封市| 绥中县| 新建县| 政和县| 若尔盖县| 两当县| 灵丘县| 江油市| 肇源县| 红安县| 景德镇市| 耒阳市| 沾益县| 浮山县| 中西区| 汕头市| 祁门县| 富蕴县| 桂阳县| 莲花县| 甘孜县| 克东县| 霍林郭勒市| 凤庆县| 肇州县| 涞水县|