精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

欧美性猛片aaaaaaa做受| 久久久久国产成人精品亚洲午夜| 欧美成人四级hd版| 国产精九九网站漫画| 欧美久久天堂| 国产精品久久久久久户外露出| 亚洲一区二区三区成人在线视频精品 | 99蜜月精品久久91| 亚洲欧美韩国综合色| 精品一区二区三区自拍图片区| 中文字幕av在线免费观看| 亚洲一区二区日韩| 亚洲欧美在线免费| 4438x全国最大成人| 中文日产幕无线码一区二区| 中文字幕制服丝袜一区二区三区 | 天天综合网久久| 白白色在线观看| 日本一区二区免费在线观看视频| 3d动漫精品啪啪一区二区三区免费| 国产情侣自拍av| 成人激情在线| 精品亚洲永久免费精品 | 91丨九色porny丨蝌蚪| 国产中文日韩欧美| 国产精品久免费的黄网站| 91精品国产自产在线观看永久∴| 亚洲欧美国产一区二区三区| 性一交一黄一片| 亚洲天堂一区二区| 五月婷婷综合在线| 日韩一二区视频| 天天综合视频在线观看| 久久久亚洲精品一区二区三区| 国产91视觉| 国产男女裸体做爰爽爽| 日韩精品亚洲专区| 欧美亚洲成人网| 黄色小视频在线免费看| 中文无码久久精品| 久久国产加勒比精品无码| 亚洲ⅴ国产v天堂a无码二区| 亚洲人挤奶视频| 日韩麻豆第一页| 好男人香蕉影院| 东京久久高清| 欧美精品一区二区在线观看| 4438x全国最大成人| 91精品国产色综合久久不卡粉嫩| 精品视频1区2区| 黄色av免费在线播放| 天堂电影一区| 色综合久久综合网欧美综合网| 日韩视频免费播放| 91豆花视频在线播放| 夜夜精品视频一区二区| 国产在线无码精品| 手机在线免费看av| 亚洲一区二区三区视频在线播放| 国产精品三级一区二区| 天堂亚洲精品| 亚洲国产精品久久人人爱蜜臀| www.欧美黄色| 55av亚洲| 在线视频中文字幕一区二区| 国产自偷自偷免费一区| 欧洲av一区二区| 欧美日韩一区二区三区免费看| 欧美日韩大尺度| 欧美黄页免费| 日韩视频中午一区| 国产视频精品视频| 亚洲人成网亚洲欧洲无码| 国产亚洲人成网站在线观看| 欧美自拍偷拍网| 中国成人一区| 97在线免费视频| 中文字幕一区在线播放| 日韩成人一级片| 91久久久久久久久| 亚洲精品久久久久久无码色欲四季| 成人免费av在线| 热re99久久精品国99热蜜月| 日本在线免费播放| 亚洲午夜一区二区| 女人另类性混交zo| 97久久中文字幕| 日韩经典第一页| 夫妇露脸对白88av| 国产精品99免费看| 日韩女优人人人人射在线视频| 亚洲天堂视频在线| 成人激情综合网站| 日本在线观看一区二区| 伊人春色在线观看| 日韩欧美在线一区| 久久艹这里只有精品| 国产主播性色av福利精品一区| 亚洲视频视频在线| 激情四射综合网| 天堂成人国产精品一区| 亚洲永久在线观看| 韩国中文免费在线视频| 一区二区三区资源| av网站在线不卡| 豆花视频一区二区| 中文字幕在线看视频国产欧美在线看完整 | 在线视频观看91| 视频福利一区| 欧美日本国产在线| 中文字幕网址在线| aaa欧美色吧激情视频| 亚洲日本精品| 综合日韩av| 欧美不卡123| 国产农村妇女精品一区| 亚洲女同同性videoxma| 97在线资源站| 黄色片免费在线观看| 色爱区综合激月婷婷| 黑森林av导航| 久久久精品国产sm调教| 欧美xxxx少妇| 欧美三级一区二区| 毛茸茸多毛bbb毛多视频| 欧美日韩国产探花| 国产一区二区丝袜| 国产色a在线| 欧美性黄网官网| 亚洲av永久无码精品| 自产国语精品视频| 91精品久久久久久久久不口人| 韩国三级在线观看久| 欧美视频中文在线看| 精品人妻一区二区三区日产| 欧美一区不卡| 91亚洲国产精品| 黄色网页网址在线免费| 欧美色图在线观看| 天天操天天舔天天射| 久久久久久穴| 欧美日韩精品免费观看| 欧亚在线中文字幕免费| 亚洲国产精品99久久| 久久久久久国产精品视频| 国产在线一区二区| 中国老女人av| 九九99久久精品在免费线bt| 久久亚洲精品一区二区| 国产精品欧美综合亚洲| 国产精品护士白丝一区av| 亚洲欧美日韩一级| 先锋资源久久| 亚洲a成v人在线观看| av在线看片| 日韩免费观看高清完整版在线观看| 91久久国产综合| 国产精品一区免费视频| 99国产精品白浆在线观看免费| 欧美成人一级| 久久久久久久国产| 色网站免费观看| 欧美日韩一二三四五区| 久久久久久国产精品无码| 日韩vs国产vs欧美| 综合久久国产| japanese色系久久精品| 欧美性受xxxx黑人猛交| 国产69久久| 制服丝袜国产精品| 久久综合亚洲色hezyo国产| 成人免费毛片片v| 欧美牲交a欧美牲交| 奇米色欧美一区二区三区| 国产精品入口福利| 日韩影视在线| 精品无人国产偷自产在线| 久久精品国产亚洲av麻豆蜜芽| 国产精品国产三级国产有无不卡 | 波多野结衣一区二区三区免费视频| 欧美精品激情blacked18| 亚洲av成人精品毛片| 欧美系列在线观看| 欧美日韩在线观看成人| 97se亚洲国产综合自在线不卡| 欧美日韩怡红院| 欧美在线高清| 日本成人黄色免费看| 欧一区二区三区| 日韩av免费在线看| 污污的视频在线观看| 亚洲美女视频网站| 国产男男gay体育生网站| 欧美视频中文在线看| 国产精品免费在线视频| 不卡影院免费观看| 在线观看岛国av| 在线视频日韩| 亚洲成人动漫在线| 国模吧精品视频| 国产精品福利视频| 欧美日韩va| 日本91av在线播放| 性xxxxfjsxxxxx欧美| 一夜七次郎国产精品亚洲| 免费国产精品视频| 3751色影院一区二区三区| 69xxxx国产| 亚洲18女电影在线观看| 翔田千里88av中文字幕| 久久精品视频免费观看| 亚洲av永久无码精品| 国内精品伊人久久久久av影院 | 四虎影院在线免费播放| 亚洲成av人片观看| 久草网站在线观看| 中文字幕va一区二区三区| 亚洲av成人片无码| 国产高清精品在线| www.国产视频.com| 日本不卡一区二区| 黑人糟蹋人妻hd中文字幕| 欧美日韩亚洲国产精品| 在线码字幕一区| 精品国产一区二区三区久久久樱花 | 人人澡人人澡人人看欧美| 国模雨婷捆绑高清在线| 久久精品国产91精品亚洲| 国产女主播在线直播| 精品夜色国产国偷在线| 五十路在线视频| 欧美精品一区二区久久久| 精品人妻伦一区二区三区久久| 欧美日韩国产一级片| 免费看av在线| 欧洲视频一区二区| 欧美日韩 一区二区三区| 色综合久久99| 无码人妻精品一区二| 日韩欧美一区二区三区| 亚洲黄网在线观看| 色综合久久天天| 青草视频在线观看免费| 欧美日韩裸体免费视频| 久久国产视频精品| 色综合激情五月| 色屁屁影院www国产高清麻豆| 狠狠躁夜夜躁人人躁婷婷91| 欧美三级韩国三级日本三斤在线观看| 亚洲图片有声小说| 日韩免费视频网站| 天天综合色天天综合色h| 久久艹免费视频| 色哟哟在线观看一区二区三区| 黄色一级视频免费看| 在线观看不卡一区| 96日本xxxxxⅹxxx17| 91精品国产91久久久久久一区二区 | 91美女免费看| 色综合久久99| 中文字幕一区二区三区四区视频 | 中文字幕第三区| 国产白丝精品91爽爽久久| 香蕉视频污视频| 91网页版在线| 正在播放国产对白害羞| 亚洲欧洲成人精品av97| 69av视频在线| 色综合天天在线| 亚洲一级黄色大片| 日韩视频在线你懂得| 四虎影视精品成人| 亚洲视频专区在线| 成人在线播放| 91精品国产色综合久久不卡98| 亚洲日本天堂| 成人欧美一区二区三区在线湿哒哒 | 国产九九精品| 污污网站免费观看| 成人综合婷婷国产精品久久| 人人妻人人藻人人爽欧美一区| 中文字幕+乱码+中文字幕一区| 国产女人18水真多毛片18精品| 亚洲大型综合色站| 色婷婷久久综合中文久久蜜桃av| 91精品福利在线一区二区三区| 欧美一级在线免费观看| 在线性视频日韩欧美| 午夜小视频福利在线观看| 日本sm极度另类视频| 色播一区二区| 欧美日韩无遮挡| 午夜欧美精品久久久久久久| 国产在线观看福利| 国产在线播精品第三| 日本高清www| 夜夜爽夜夜爽精品视频| 亚洲午夜无码久久久久| 精品sm在线观看| 日本免费视频在线观看| 97色在线观看| 国产专区精品| 色噜噜狠狠色综合网| 今天的高清视频免费播放成人| 日本超碰在线观看| 99免费精品在线| 欧美特级一级片| 欧洲另类一二三四区| 欧美综合视频在线| 欧美老女人xx| 五月天色综合| 日韩国产美国| 亚洲美女毛片| 国产在线a视频| 成人免费在线视频| 涩涩视频在线观看| 亚洲精品二三区| 欧美性爽视频| 97国产超碰| 91精品福利| 黄色一级片免费的| 国产精品久久久久久久久免费桃花 | 91免费国产视频| 精品国内自产拍在线观看视频 | 国产精品九九九九九九| 精品视频1区2区| 999在线视频| 国产精品视频资源| 成人激情开心网| 波多野结衣作品集| 久久久久久亚洲综合影院红桃| 中国一级特黄毛片| 日韩精品免费在线视频| 麻豆视频在线看| 国产一区免费在线| 亚洲欧洲视频| 一级特黄a大片免费| 午夜影院久久久| 无码国产伦一区二区三区视频| 欧美激情国产精品| 大奶在线精品| 日韩精品 欧美| 99热精品国产| 69国产精品视频免费观看| 亚洲精品一区二区三区婷婷月| 欧美gv在线| 欧美日韩日本网| 蜜臀av性久久久久蜜臀aⅴ流畅| 97在线观看免费视频| 欧美特级限制片免费在线观看| 91亚洲精选| 91色精品视频在线| 欧美日韩一视频区二区| 四虎精品一区二区| 欧美日韩国产精品专区| 欧美日韩国产综合视频| 国产精品免费久久久久影院| 欧美偷拍综合| 欧美视频亚洲图片| 亚洲综合色婷婷| 三级视频在线播放| 国产精品久久久久久亚洲调教| 色综合天天爱| 老女人性生活视频| 婷婷开心久久网| 黄色片在线看| 91欧美精品午夜性色福利在线| 欧美日韩三级| 欧美性xxxx图片| 欧美日韩免费高清一区色橹橹 | 日韩av免费网站| 91视频综合| 日韩高清一二三区| 日韩欧美在线网址| 九色porny在线| 精品无人区一区二区三区| 久久久久久婷| 青青草免费av| 亚洲色图综合久久| 精品国产一区二| 1024精品视频| 亚洲欧洲99久久| 香蕉视频免费在线看| 国产精品视频一区二区高潮| 午夜日韩视频| 性欧美一区二区| 精品三级在线观看| 日本一道高清亚洲日美韩| 狠狠噜天天噜日日噜| 久久精品亚洲国产奇米99| 国产成人精品亚洲精品色欲| 欧洲永久精品大片ww免费漫画| 天天做天天爱天天综合网| 天天插天天射天天干| 欧美日韩成人综合在线一区二区| 波多野结衣视频一区二区| 欧美亚洲视频一区| 久久色成人在线| 成人午夜免费在线观看| 国产精品一区二区女厕厕|