精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Spring Boot 接口敏感字段脫敏的五大"王炸"方案

開發 前端
接口敏感字段脫敏,通過對關鍵信息進行部分隱藏、替換或加密等操作,在不影響數據正常使用和分析的前提下,最大程度降低敏感信息暴露風險。本篇文章我們將采用5種技術方案來實現敏感字段的脫敏。

環境:SpringBoot3.4.2

1. 簡介

在實際項目中,經常會遇到一些敏感字段信息,像用戶的身份證號碼、銀行卡卡號、詳細家庭住址、手機號碼以及各類密碼等。若這些敏感字段在接口傳輸或展示過程中未作脫敏處理,一旦遭遇數據泄露事件,將給用戶帶來嚴重損失,包括財產被盜刷、個人隱私曝光,甚至可能引發身份盜用等風險。

接口敏感字段脫敏,通過對關鍵信息進行部分隱藏、替換或加密等操作,在不影響數據正常使用和分析的前提下,最大程度降低敏感信息暴露風險。

本篇文章我們將采用5種技術方案來實現敏感字段的脫敏。

2.實戰案例

準備環境

public class User {
  private Long id ;
  private String name ;
  private Integer age ;
  private String phone ;
  private String idNo ;
  // getters, setters, constructors
}
// Controller接口
@RestController
@RequestMapping("/users")
public class UserController {
  @GetMapping
  public ResponseEntity<User> query() {
    return ResponseEntity.ok(new User(666L, "Pack_xg", 33, 
      "13399065789", "320311198512185678")) ;
  }
}

我們在編寫一個工具類,統一都由該工具類處理敏感字段

public class MaskUtils {
  public static String maskString(String input) {
    int length = input.length();
    // 計算xxx、***、yyy的長度(總長度=xxx+***+yyy)
    int xxxLength = length / 3;        // 前1/3
    int yyyLength = length / 3;        // 后1/3
    // 中間剩余部分用*
    int starLength = length - xxxLength - yyyLength;
    // 確保至少各保留1個字符(避免xxx或yyy為0)
    xxxLength = Math.max(1, xxxLength);
    yyyLength = Math.max(1, yyyLength);
    starLength = Math.max(1, starLength);
    // 重新調整(防止因取整導致總和超出原長度)
    while (xxxLength + starLength + yyyLength > length) {
      if (xxxLength > 1) xxxLength--;
      else if (starLength > 1) starLength--;
      else yyyLength--;
    }
    String xxx = input.substring(0, xxxLength);
    String yyy = input.substring(length - yyyLength);
    String stars = repeat("*", starLength);
    return xxx + stars + yyy;
  }


  private static String repeat(String s, int count) {
    return new String(new char[count]).replace("\0", s);
  }
}

2.1 自定義Json序列化

public class CommonMaskSerializer extends JsonSerializer<String> {
  @Override
  public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
    if (value == null || value.length() < 6) {
      gen.writeString("***");
      return;
    }
    String masked = MaskUtils.maskString(value) ;
    gen.writeString(masked);
  }
}

接下來,修改實體對象如下:

public class User {
  @JsonSerialize(using = CommonMaskSerializer.class)
  private String phone ;
  @JsonSerialize(using = CommonMaskSerializer.class)
  private String idNo ;
}

輸出結果

圖片

2.2 自定義Jackson模塊

上一種方法是字段級別的,雖然精準,但若多個實體都需要相同的邏輯,則會顯得冗余繁瑣。為了避免將所有內容都與注解綁定,我們可以通過自定義模塊方式注冊自定義序列化器,這些序列化器可應用于整個類型。如下代碼實現:

@Configuration
public class JacksonConfig {
  @Bean
  Jackson2ObjectMapperBuilderCustomizer maskingCustomizer() {
    return builder -> builder.modules(new MaskingModule());
  }
  public static final class MaskingModule extends SimpleModule {
    // 這里我們固定了處理那些字段名,你也可以將其放到配置文件中進行動態管理
    private static final Set<String> fields = Set.of("idNo", "phone") ;
    public MaskingModule() {
      setSerializerModifier(new BeanSerializerModifier() {
        @Override
        public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc,
            List<BeanPropertyWriter> props) {
          for (int i = 0; i < props.size(); i++) {
            BeanPropertyWriter w = props.get(i);
            if (w.getType().isTypeOrSubTypeOf(String.class) && fields.contains(w.getName())) {
              props.set(i, new MaskingWriter(w));
            }
          }
          return props;
        }
      });
    }
  }
  static final class MaskingWriter extends BeanPropertyWriter {
    private static final long serialVersionUID = 1L;
    MaskingWriter(BeanPropertyWriter base) {
      super(base);
    }
    @Override
    public void serializeAsField(Object bean, JsonGenerator gen, com.fasterxml.jackson.databind.SerializerProvider prov)
        throws Exception {
      Object raw = get(bean);
      if (raw == null) {
        super.serializeAsField(bean, gen, prov);
        return;
      }
      String masked = MaskUtils.maskString(raw.toString());
      gen.writeStringField(getName(), masked);
    }
  }
}

接下來,我們將實體類上的@JsonSerialize注解刪除,一樣能達到效果,并且此種方式不需要我們對實體類進行任何的修改,這能滿足絕大多數的場景。

圖片圖片

2.3 使用AOP技術

利用AOP技術,在Controller接口返回后,通過反射技術對返回值進行處理。

自定義注解,只有返回值的類型上使用了該注解才進行處理

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Mask {


  /**需要處理的字段*/
  String[] value() default {} ;
}

定義切面

@Aspect
@Component
public class MaskAspect {
  private static final Map<Class<?>, List<PropMethod>> cache = new ConcurrentHashMap<>();
  @AfterReturning(pointcut = "execution(* com.pack.sensitive.controller..*.*(..))", returning = "response")
  public void applyMasking(Object response) throws Throwable {
    Object target = response;
    if (response instanceof ResponseEntity entity) {
      target = entity.getBody();
    }
    Class<?> clazz = target.getClass();
    Mask mask = clazz.getAnnotation(Mask.class);
    if (mask == null) {
      return;
    }
    List<String> fields = Arrays.asList(mask.value());
    if (fields.isEmpty()) {
      return ;
    }
    List<PropMethod> props = cache.get(clazz);
    if (props == null) {
      BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
      for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) {
        if (fields.contains(pd.getName())) {
          props = cache.computeIfAbsent(clazz, key -> new ArrayList<>()) ;
          props.add(new PropMethod(pd.getReadMethod(), pd.getWriteMethod())) ;
        }
      }
    }
    if (props != null) {
      for (PropMethod pm : props) {
        pm.setter.invoke(target, MaskUtils.maskString((String) pm.getter.invoke(target))) ;
      }
    }
  }
  static record PropMethod(Method getter, Method setter) {
  }
}

修改User實體對象如下

@Mask({"phone", "idNo"})
public class User {
  private Long id ;
  private String name ;
  private Integer age ;
  private String phone ;
  private String idNo ;
}

調用Controller接口

圖片圖片

2.4 使用ResponseBodyAdvice

我們可以利用Spring MVC的核心組件 ResponseBodyAdvice,該組件能夠在控制器方法返回的響應體被序列化輸出前,對返回數據進行攔截和處理。此種方式不是AOP技術,這里就完全使用反射技術實現脫敏。

在該方案中,我們還是利用Mask注解來進行標記處理,整體的處理與AOP基本相同。

@RestControllerAdvice
public class MaskBodyAdvice implements ResponseBodyAdvice<Object> {
  private static final Map<Class<?>, List<PropMethod>> cache = new ConcurrentHashMap<>();


  @Override
  public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
    return true ;
  }
  @Override
  public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
      Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
      ServerHttpResponse response) {
    if (body == null) {
      return null;
    }


    if (body instanceof ResponseEntity entity) {
      body = entity.getBody() ;
    }
    if (body instanceof Collection<?> coll) {
      for (Object o : coll) {
        try {
          maskField(o);
        } catch (Throwable e) {}
      }
      return body;
    }
    try {
      maskField(body);
    } catch (Throwable e) {}
    return body;
  }
  private void maskField(Object target) throws Throwable {
    // 這里的處理邏輯與上面的AOP一樣 
  }
}

此種方案核心與AOP一樣,只是這里不需要代理技術而已。

2.5 使用@JsonFilter

我們還可以配置 Jackson 屬性過濾器,也就是在需要處理的類上添加 @JsonFilter 注解,這樣我們就不需要為每個對象單獨添加注解的字段級過濾。

首先,修改實體對象

@JsonFilter("maskFilter")
public class User {
  // ...
}

這里的名稱 maskFilter 隨意。

接下來,自定義ObjectMapper

@Configuration
public class MaskFilterConfig {
  private static final Set<String> fields = Set.of("idNo", "phone");
  @Bean
  Jackson2ObjectMapperBuilderCustomizer maskingFilterCustomizer() {
    return builder -> {
      SimpleFilterProvider filters = new SimpleFilterProvider().addFilter("maskFilter", new SimpleBeanPropertyFilter() {
        @Override
        public void serializeAsField(Object pojo, JsonGenerator gen, SerializerProvider prov, PropertyWriter writer)
            throws Exception {
          if (fields.contains(writer.getName())) {
            Object val = (writer instanceof BeanPropertyWriter bpw) ? bpw.get(pojo) : null;
            if (val == null) {
              writer.serializeAsField(pojo, gen, prov);
              return;
            }
            gen.writeStringField(writer.getName(), MaskUtils.maskString(val.toString()));
            return;
          }
          writer.serializeAsField(pojo, gen, prov);
        }
      });
      builder.filters(filters);
    };
  }
}

通過上面的方法也能也能達到對敏感字段的處理。

責任編輯:武曉燕 來源: Springboot全家桶實戰案例
相關推薦

2025-08-01 09:03:06

Spring重試機制網絡

2024-01-01 14:19:11

2025-06-06 08:28:56

2025-05-14 01:00:00

Spring工具工廠類

2019-06-04 10:40:07

2019-08-30 13:00:12

MySQL高可用數據庫

2023-05-17 08:00:00

ChatGPT人工智能

2022-04-30 08:58:00

SpringJava開發

2014-02-20 11:11:52

2012-11-26 09:54:56

2025-04-07 02:33:00

項目開發Spring

2024-03-29 08:56:47

2025-10-27 02:15:00

2013-05-07 09:24:53

BYOD

2017-12-25 10:34:18

技術預測機遇

2025-08-08 05:00:00

IT職業CIOAI

2017-04-19 22:58:28

MySQL分布式數據

2011-08-16 09:20:57

云計算云管理

2015-07-02 09:48:11

2019-12-18 10:20:30

混合云公共云私有云
點贊
收藏

51CTO技術棧公眾號

韩国主播福利视频一区二区三区| 一级全黄裸体免费视频| 久久夜色电影| 欧美日韩国产限制| 日韩欧美视频第二区| 一级二级三级视频| 亚洲黄色影片| 综合av色偷偷网| 日本黄色www| 神马久久午夜| 国产精品久久久久久久蜜臀| www.一区二区三区| 天堂网视频在线| 91亚洲国产| 亚洲国产精品大全| av中文字幕网址| 123区在线| 欧美高清在线一区二区| 亚洲aⅴ男人的天堂在线观看| 日韩av电影网| 国产精品二区不卡| 日韩精品视频在线观看免费| 中文字幕亚洲影院| 午夜久久中文| 一区二区三区四区国产精品| 美国av一区二区三区| 国产美女主播在线观看| 爽好久久久欧美精品| 欧美国产日韩一区二区| 亚洲一级黄色录像| 美女一区二区在线观看| 这里只有精品视频在线观看| 日韩中文字幕二区| 国产盗摄精品一区二区酒店| 亚洲视频一区二区在线观看| 久久99九九| 亚洲第一黄色片| 蜜臀久久久久久久| 日韩av片永久免费网站| 国产在线成人精品午夜| 天天影视综合| 这里精品视频免费| 老牛影视av老牛影视av| 超碰在线成人| 欧美一区二区三区色| 亚洲国产高清av| jizz内谢中国亚洲jizz| 亚洲成年人网站在线观看| 国产人妻互换一区二区| 亚洲xxxxxx| 日本一区二区在线不卡| 激情欧美一区二区三区中文字幕| 亚洲av无码片一区二区三区 | 国产天堂视频在线观看| 黄色网址在线免费观看| 中文天堂在线一区| 日本一区免费观看| 好男人免费精品视频| 久久综合九色综合欧美就去吻| 国产女人水真多18毛片18精品 | 日韩精品视频中文在线观看 | 97久久精品| 欧美不卡视频一区| 日本中文字幕有码| 成人免费在线电影网| 精品日韩在线观看| 欧美久久久久久久久久久| 视频精品二区| 日韩欧美视频在线| 午夜影院福利社| xxxxxhd亚洲人hd| 亚洲精品电影在线| 一起草在线视频| 免费看成人吃奶视频在线| 亚洲精品在线视频| 国产在线综合视频| 88国产精品视频一区二区三区| 欧美麻豆久久久久久中文| 欧美日韩人妻精品一区二区三区| 国内久久精品| 97成人超碰免| 国产精品午夜一区二区| 紧缚捆绑精品一区二区| 99久久自偷自偷国产精品不卡| 亚洲精品国产一区二| 91啪亚洲精品| 日韩欧美亚洲精品| av网站在线看| 岛国视频午夜一区免费在线观看| 国产一线二线三线在线观看| 日韩综合久久| 亚洲第一区第二区| 中文字幕在线观看免费高清| 天天久久综合| 国产91精品青草社区| 中文字幕一区二区三区四区视频| 国产精品一级黄| 美脚丝袜一区二区三区在线观看| 91美女视频在线| 一区二区三区国产豹纹内裤在线 | 老司机福利在线观看| 亚洲一区二区日韩| 91国内在线视频| 亚洲图片小说视频| av成人老司机| 亚洲一区二区高清视频| 国产深夜视频在线观看| 日本韩国欧美一区二区三区| 97超碰免费在线观看| 欧美亚洲色图校园春色| 久久天天躁日日躁| 精品久久久久久久久久久久久久久久| 国产精品一级片| 日韩欧美99| 久草在线中文最新视频| 91精品欧美一区二区三区综合在| 91精品人妻一区二区| 欧美日韩亚洲一区三区| 国产精品露脸自拍| 天天干天天色天天| 伊人婷婷欧美激情| 亚洲欧美自偷自拍另类| 秋霞在线一区| 欧美激情在线播放| 97人妻一区二区精品免费视频| 久久蜜臀中文字幕| 国产成人无码a区在线观看视频| crdy在线观看欧美| 色噜噜国产精品视频一区二区| 五月天激情国产综合婷婷婷| 高清不卡一二三区| 免费成人深夜夜行网站视频| 91精品国产66| 亚洲片国产一区一级在线观看| 亚洲精品午夜久久久久久久| 国产成人在线视频免费播放| 在线观看亚洲视频啊啊啊啊| av一区在线播放| 日韩精品免费在线观看| 色哟哟一一国产精品| 久久午夜精品一区二区| 久久精品美女| 国产探花在线观看| 日韩亚洲欧美一区二区三区| 国产成人无码精品久久二区三| 国产欧美一级| 成人h在线播放| 黄色免费在线观看网站| 欧美无人高清视频在线观看| 日本黄色网址大全| 西西裸体人体做爰大胆久久久| 国产精品一区二区欧美| 青草在线视频| 日韩天堂在线观看| 天堂网avav| 国产在线精品一区在线观看麻豆| 亚洲高清视频一区| 香蕉成人av| 国产午夜精品一区二区三区| 99超碰在线观看| 91女厕偷拍女厕偷拍高清| 日本精品一区在线观看| 西野翔中文久久精品国产| 97精品免费视频| 二区三区在线视频| 亚洲午夜久久久久久久久电影网| 黑森林av导航| 影音先锋亚洲精品| 国产精品伊人日日| 丁香高清在线观看完整电影视频 | 高潮毛片又色又爽免费| 26uuu久久天堂性欧美| 国产乱淫av片杨贵妃| 成人在线tv视频| 88国产精品欧美一区二区三区| 国产综合在线播放| 图片区日韩欧美亚洲| 美女脱光内衣内裤| 日本美女视频一区二区| 亚洲欧美久久234| 自拍偷拍亚洲图片| 久久夜色精品国产| 老熟妇高潮一区二区高清视频| 亚洲va天堂va国产va久| 女尊高h男高潮呻吟| 日本不卡视频一二三区| 男插女免费视频| 国产精品xxx在线观看| 茄子视频成人在线| 91在线看黄| 日韩视频一区二区三区| 激情视频在线播放| 91蜜桃网址入口| 日本xxxx黄色| 午夜电影亚洲| 你懂的网址一区二区三区| 色综合一区二区日本韩国亚洲| 欧美精品免费在线观看| 天堂成人在线视频| 欧美亚一区二区| 精品99在线观看| 中文字幕免费在线观看视频一区| 亚洲理论中文字幕| 亚洲欧洲日本一区二区三区| 欧洲精品久久| 日韩精品久久久久久久软件91| 欧美又大又硬又粗bbbbb| av在线三区| 精品噜噜噜噜久久久久久久久试看 | 中文字幕观看视频| 亚洲曰韩产成在线| 亚洲第一综合网| 久久爱另类一区二区小说| 成人黄色av片| 水蜜桃久久夜色精品一区| 狠狠色伊人亚洲综合网站色| 欧美日韩伦理一区二区| 2021久久精品国产99国产精品| 一级毛片视频在线观看| 精品国产露脸精彩对白| 中文字幕在线2018| 精品久久久视频| 综合五月激情网| 久久久www免费人成精品| 真实乱偷全部视频| 日韩中文字幕亚洲一区二区va在线| 日韩成人三级视频| 色综合天天爱| 麻豆av一区二区| 亚州一区二区| 国产日本欧美在线观看| av亚洲一区二区三区| 97在线免费视频| 亚洲七七久久综合桃花剧情介绍| 国产亚洲精品va在线观看| 韩国av电影在线观看| 欧美一级搡bbbb搡bbbb| 波多野结衣在线观看视频| 天天做天天摸天天爽国产一区| 国产福利视频网站| **网站欧美大片在线观看| 亚洲黄色小说视频| 99国产麻豆精品| 亚洲精品一区二区18漫画| 美女任你摸久久| 午夜两性免费视频| 丝袜美腿亚洲一区二区图片| 成人在线免费观看av| 18成人免费观看视频| www精品久久| 亚洲性色视频| 日韩精品视频在线观看视频| 欧美a级在线| 国产青草视频在线观看| 欧美精品一线| 老汉色影院首页| 亚洲成人一区| 亚洲自拍偷拍一区二区三区| 久久久久电影| 欧美 日韩 国产 在线观看| 日韩久久久久| 亚洲欧美影院| 欧美破处大片在线视频| 国内外成人激情免费视频| 一区二区不卡| 六月婷婷激情网| 最新成人av网站| 精品视频在线观看一区| 在线亚洲免费| heyzo国产| 日韩成人dvd| 午夜免费福利视频在线观看| 久久99精品国产麻豆婷婷| 激情五月俺来也| 国产精品99久久不卡二区| 伊人av在线播放| 成人激情校园春色| 国产一级二级视频| 91视频.com| 娇妻被老王脔到高潮失禁视频| 国产精品麻豆视频| 天天天天天天天天操| 亚洲综合免费观看高清在线观看| 久久亚洲av午夜福利精品一区| 亚洲成人免费视频| 老熟妇仑乱一区二区av| 欧美日韩在线综合| 亚洲国产精品久久久久久6q| 日韩av网址在线观看| 欧美777四色影视在线| 国产一区二区激情| 91欧美在线视频| 韩国福利视频一区| 国产日韩另类视频一区| 成人有码在线播放| av动漫精品一区二区| 久久久综合亚洲91久久98| 欧美一区二区三| 日韩中文在线字幕| 久久综合五月| 人妻巨大乳一二三区| 91亚洲精品久久久蜜桃网站 | 亚洲另类一区二区| 国产视频91在线| 欧美日韩成人在线| 空姐吹箫视频大全| 国产亚洲欧美一区| 国产精品一品| 国产精品人成电影| 日韩精品福利一区二区三区| 永久域名在线精品| 亚洲久久一区| 99国产精品久久久久久| 久久精品亚洲国产奇米99| 麻豆成人在线视频| 在线观看www91| a天堂中文在线观看| 国产一区二区三区四区福利| 毛片大全在线观看| 国产精品视频一| 奇米影视777在线欧美电影观看| 一区二区三区不卡在线| 99riav国产精品| 无套白嫩进入乌克兰美女| 国产午夜亚洲精品不卡| 国产极品美女高潮无套嗷嗷叫酒店| 欧美日韩一区国产| 精品久久av| 69久久夜色精品国产69| 日本精品一区二区三区在线观看视频| 你懂的网址一区二区三区| 日韩视频中文| 国产免费无码一区二区| 国产精品国产精品国产专区不蜜 | 国产精品99久久久久久动医院| 人妻内射一区二区在线视频 | 综合日韩在线| 日韩在线不卡一区| 久久九九久久九九| 日韩视频免费观看高清| 欧美一区二区三区在线观看| 男人天堂久久久| 国产精品三级美女白浆呻吟| 亚洲人成网www| 国产又大又硬又粗| eeuss鲁片一区二区三区在线观看| 青草影院在线观看| 色婷婷综合久久久中文一区二区| 天堂中文在线8| 国内精品视频久久| 97人人澡人人爽91综合色| 少妇久久久久久被弄到高潮| 国产在线国偷精品产拍免费yy| 亚洲熟女毛茸茸| 欧美影院一区二区| 日韩黄色影院| 国产精品高潮呻吟视频| 国产一区二区三区电影在线观看 | 免费a在线看| 91免费综合在线| 88国产精品视频一区二区三区| 亚洲一区二区三区观看| 亚洲日穴在线视频| 国产人妻精品一区二区三区| 亚洲欧洲一区二区三区久久| 2021中文字幕在线| 久久99热只有频精品91密拍| 国产欧美短视频| aaaaa一级片| 欧美影视一区二区三区| 国产一级片在线| 国产成人精品视频在线观看| 成人精品视频| 日韩av.com| 一级日本不卡的影视| aa视频在线免费观看| 97人人模人人爽人人喊中文字| 女仆av观看一区| 欧美性潮喷xxxxx免费视频看| aaa欧美日韩| 伊人久久中文字幕| 蜜臀久久99精品久久久无需会员 | 欧美日韩国产综合新一区| 欧美91精品久久久久国产性生爱| 国产精品xxx视频| 中文字幕免费精品| 黄色国产在线视频| 欧美性xxxx极品hd满灌| 亚洲成人影院麻豆| 国产精品swag| 久久天堂精品| 欧美成欧美va| 亚洲另类欧美自拍| 久久久久久久性潮| 米仓穗香在线观看| 久久综合久久鬼色中文字| 亚洲天堂自拍偷拍| 久久精品国产一区二区电影| 免费成人蒂法| 色播五月激情五月|