<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Springboot 日志、配置文件、接口數(shù)據(jù)如何脫敏?老鳥(niǎo)們都是這樣玩的!

          共 29177字,需瀏覽 59分鐘

           ·

          2021-09-13 21:02

          一、前言

          核心隱私數(shù)據(jù)無(wú)論對(duì)于企業(yè)還是用戶來(lái)說(shuō)尤其重要,因此要想辦法杜絕各種隱私數(shù)據(jù)的泄漏。下面陳某帶大家從以下三個(gè)方面講解一下隱私數(shù)據(jù)如何脫敏,也是日常開(kāi)發(fā)中需要注意的:

          1. 配置文件數(shù)據(jù)脫敏
          2. 接口返回?cái)?shù)據(jù)脫敏
          3. 日志文件數(shù)據(jù)脫敏

          文章目錄如下:

          二、配置文件如何脫敏?

          經(jīng)常會(huì)遇到這樣一種情況:項(xiàng)目的配置文件中總有一些敏感信息,比如數(shù)據(jù)源的url、用戶名、密碼....這些信息一旦被暴露那么整個(gè)數(shù)據(jù)庫(kù)都將會(huì)被泄漏,那么如何將這些配置隱藏呢?

          以前都是手動(dòng)將加密之后的配置寫入到配置文件中,提取的時(shí)候再手動(dòng)解密,當(dāng)然這是一種思路,也能解決問(wèn)題,但是每次都要手動(dòng)加密、解密不覺(jué)得麻煩嗎?

          今天介紹一種方案,讓你在無(wú)感知的情況下實(shí)現(xiàn)配置文件的加密、解密。利用一款開(kāi)源插件:jasypt-spring-boot。項(xiàng)目地址如下:

          https://github.com/ulisesbocchio/jasypt-spring-boot

          使用方法很簡(jiǎn)單,整合Spring Boot 只需要添加一個(gè)starter。

          1. 添加依賴

          <dependency>
                  <groupId>com.github.ulisesbocchio</groupId>
                  <artifactId>jasypt-spring-boot-starter</artifactId>
                  <version>3.0.3</version>
          </dependency>  

          2. 配置秘鑰

          在配置文件中添加一個(gè)加密的秘鑰(任意),如下:

          jasypt:
            encryptor:
              password: Y6M9fAJQdU7jNp5MW

          當(dāng)然將秘鑰直接放在配置文件中也是不安全的,我們可以在項(xiàng)目啟動(dòng)的時(shí)候配置秘鑰,命令如下:

          java -jar xxx.jar  -Djasypt.encryptor.password=Y6M9fAJQdU7jNp5MW

          3. 生成加密后的數(shù)據(jù)

          這一步驟是將配置明文進(jìn)行加密,代碼如下:

          @SpringBootTest
          @RunWith(SpringRunner.class)
          public class SpringbootJasyptApplicationTests 
          {

              /**
               * 注入加密方法
               */

              @Autowired
              private StringEncryptor encryptor;

              /**
               * 手動(dòng)生成密文,此處演示了url,user,password
               */

              @Test
              public void encrypt() {
                  String url = encryptor.encrypt("jdbc\\:mysql\\://127.0.0.1\\:3306/test?useUnicode\\=true&characterEncoding\\=UTF-8&zeroDateTimeBehavior\\=convertToNull&useSSL\\=false&allowMultiQueries\\=true&serverTimezone=Asia/Shanghai");
                  String name = encryptor.encrypt("root");
                  String password = encryptor.encrypt("123456");
                  System.out.println("database url: " + url);
                  System.out.println("database name: " + name);
                  System.out.println("database password: " + password);
                  Assert.assertTrue(url.length() > 0);
                  Assert.assertTrue(name.length() > 0);
                  Assert.assertTrue(password.length() > 0);
              }
          }

          上述代碼對(duì)數(shù)據(jù)源的url、user、password進(jìn)行了明文加密,輸出的結(jié)果如下:

          database url: szkFDG56WcAOzG2utv0m2aoAvNFH5g3DXz0o6joZjT26Y5WNA+1Z+pQFpyhFBokqOp2jsFtB+P9b3gB601rfas3dSfvS8Bgo3MyP1nojJgVp6gCVi+B/XUs0keXPn+pbX/19HrlUN1LeEweHS/LCRZslhWJCsIXTwZo1PlpXRv3Vyhf2OEzzKLm3mIAYj51CrEaN3w5cMiCESlwvKUhpAJVz/uXQJ1spLUAMuXCKKrXM/6dSRnWyTtdFRost5cChEU9uRjw5M+8HU3BLemtcK0vM8iYDjEi5zDbZtwxD3hA=

          database name: L8I2RqYPptEtQNL4x8VhRVakSUdlsTGzEND/3TOnVTYPWe0ZnWsW0/5JdUsw9ulm

          database password: EJYCSbBL8Pmf2HubIH7dHhpfDZcLyJCEGMR9jAV3apJtvFtx9TVdhUPsAxjQ2pnJ

          4. 將加密后的密文寫入配置

          jasypt默認(rèn)使用ENC()包裹,此時(shí)的數(shù)據(jù)源配置如下:

          spring:
            datasource:
              #   數(shù)據(jù)源基本配置
              username: ENC(L8I2RqYPptEtQNL4x8VhRVakSUdlsTGzEND/3TOnVTYPWe0ZnWsW0/5JdUsw9ulm)
              password: ENC(EJYCSbBL8Pmf2HubIH7dHhpfDZcLyJCEGMR9jAV3apJtvFtx9TVdhUPsAxjQ2pnJ)
              driver-class-name: com.mysql.jdbc.Driver
              url: ENC(szkFDG56WcAOzG2utv0m2aoAvNFH5g3DXz0o6joZjT26Y5WNA+1Z+pQFpyhFBokqOp2jsFtB+P9b3gB601rfas3dSfvS8Bgo3MyP1nojJgVp6gCVi+B/XUs0keXPn+pbX/19HrlUN1LeEweHS/LCRZslhWJCsIXTwZo1PlpXRv3Vyhf2OEzzKLm3mIAYj51CrEaN3w5cMiCESlwvKUhpAJVz/uXQJ1spLUAMuXCKKrXM/6dSRnWyTtdFRost5cChEU9uRjw5M+8HU3BLemtcK0vM8iYDjEi5zDbZtwxD3hA=)
              type: com.alibaba.druid.pool.DruidDataSource

          上述配置是使用默認(rèn)的prefix=ENC(、suffix=),當(dāng)然我們可以根據(jù)自己的要求更改,只需要在配置文件中更改即可,如下:

          jasypt:
            encryptor:
              ## 指定前綴、后綴
              property:
                prefix: 'PASS('
                suffix: ')'

          那么此時(shí)的配置就必須使用PASS()包裹才會(huì)被解密,如下:

          spring:
            datasource:
              #   數(shù)據(jù)源基本配置
              username: PASS(L8I2RqYPptEtQNL4x8VhRVakSUdlsTGzEND/3TOnVTYPWe0ZnWsW0/5JdUsw9ulm)
              password: PASS(EJYCSbBL8Pmf2HubIH7dHhpfDZcLyJCEGMR9jAV3apJtvFtx9TVdhUPsAxjQ2pnJ)
              driver-class-name: com.mysql.jdbc.Driver
              url: PASS(szkFDG56WcAOzG2utv0m2aoAvNFH5g3DXz0o6joZjT26Y5WNA+1Z+pQFpyhFBokqOp2jsFtB+P9b3gB601rfas3dSfvS8Bgo3MyP1nojJgVp6gCVi+B/XUs0keXPn+pbX/19HrlUN1LeEweHS/LCRZslhWJCsIXTwZo1PlpXRv3Vyhf2OEzzKLm3mIAYj51CrEaN3w5cMiCESlwvKUhpAJVz/uXQJ1spLUAMuXCKKrXM/6dSRnWyTtdFRost5cChEU9uRjw5M+8HU3BLemtcK0vM8iYDjEi5zDbZtwxD3hA=)
              type: com.alibaba.druid.pool.DruidDataSource

          5. 總結(jié)

          jasypt還有許多高級(jí)用法,比如可以自己配置加密算法,具體的操作可以參考Github上的文檔。

          三、接口返回?cái)?shù)據(jù)如何脫敏?

          通常接口返回值中的一些敏感數(shù)據(jù)也是要脫敏的,比如身份證號(hào)、手機(jī)號(hào)碼、地址.....通常的手段就是用*隱藏一部分?jǐn)?shù)據(jù),當(dāng)然也可以根據(jù)自己需求定制。

          言歸正傳,如何優(yōu)雅的實(shí)現(xiàn)呢?有兩種實(shí)現(xiàn)方案,如下:

          • 整合Mybatis插件,在查詢的時(shí)候針對(duì)特定的字段進(jìn)行脫敏

          • 整合Jackson,在序列化階段對(duì)特定字段進(jìn)行脫敏

          • 基于Sharding Sphere實(shí)現(xiàn)數(shù)據(jù)脫敏

          第一種方案網(wǎng)上很多實(shí)現(xiàn)方式,下面演示第二種,整合Jackson。

          1. 自定義一個(gè)Jackson注解

          需要自定義一個(gè)脫敏注解,一旦有屬性被標(biāo)注,則進(jìn)行對(duì)應(yīng)得脫敏,如下:

          /**
           * 自定義jackson注解,標(biāo)注在屬性上
           */

          @Retention(RetentionPolicy.RUNTIME)
          @Target(ElementType.FIELD)
          @JacksonAnnotationsInside
          @JsonSerialize(using = SensitiveJsonSerializer.class)
          public @interface Sensitive 
          {
              //脫敏策略
              SensitiveStrategy strategy();
          }

          2. 定制脫敏策略

          針對(duì)項(xiàng)目需求,定制不同字段的脫敏規(guī)則,比如手機(jī)號(hào)中間幾位用*替代,如下:

          /**
           * 脫敏策略,枚舉類,針對(duì)不同的數(shù)據(jù)定制特定的策略
           */

          public enum SensitiveStrategy {
              /**
               * 用戶名
               */

              USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)""$1*$2")),
              /**
               * 身份證
               */

              ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\w{4})""$1****$2")),
              /**
               * 手機(jī)號(hào)
               */

              PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})""$1****$2")),
              /**
               * 地址
               */

              ADDRESS(s -> s.replaceAll("(\\S{3})\\S{2}(\\S*)\\S{2}""$1****$2****"));


              private final Function<String, String> desensitizer;

              SensitiveStrategy(Function<String, String> desensitizer) {
                  this.desensitizer = desensitizer;
              }

              public Function<String, String> desensitizer() {
                  return desensitizer;
              }
          }

          以上只是提供了部分,具體根據(jù)自己項(xiàng)目要求進(jìn)行配置。

          3. 定制JSON序列化實(shí)現(xiàn)

          下面將是重要實(shí)現(xiàn),對(duì)標(biāo)注注解@Sensitive的字段進(jìn)行脫敏,實(shí)現(xiàn)如下:

          /**
           * 序列化注解自定義實(shí)現(xiàn)
           * JsonSerializer<String>:指定String 類型,serialize()方法用于將修改后的數(shù)據(jù)載入
           */

          public class SensitiveJsonSerializer extends JsonSerializer<Stringimplements ContextualSerializer {
              private SensitiveStrategy strategy;

              @Override
              public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                  gen.writeString(strategy.desensitizer().apply(value));
              }

              /**
               * 獲取屬性上的注解屬性
               */

              @Override
              public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {

                  Sensitive annotation = property.getAnnotation(Sensitive.class);
                  if (Objects.nonNull(annotation)&&Objects.equals(String.classproperty.getType().getRawClass())) {
                      this.strategy = annotation.strategy();
                      return this;
                  }
                  return prov.findValueSerializer(property.getType(), property);

              }
          }

          4. 定義Person類,對(duì)其數(shù)據(jù)脫敏

          使用注解@Sensitive注解進(jìn)行數(shù)據(jù)脫敏,代碼如下:

          @Data
          public class Person {
              /**
               * 真實(shí)姓名
               */

              @Sensitive(strategy = SensitiveStrategy.USERNAME)
              private String realName;
              /**
               * 地址
               */

              @Sensitive(strategy = SensitiveStrategy.ADDRESS)
              private String address;
              /**
               * 電話號(hào)碼
               */

              @Sensitive(strategy = SensitiveStrategy.PHONE)
              private String phoneNumber;
              /**
               * 身份證號(hào)碼
               */

              @Sensitive(strategy = SensitiveStrategy.ID_CARD)
              private String idCard;
          }

          5. 模擬接口測(cè)試

          以上4個(gè)步驟完成了數(shù)據(jù)脫敏的Jackson注解,下面寫個(gè)controller進(jìn)行測(cè)試,代碼如下:

          @RestController
          public class TestController {
              @GetMapping("/test")
              public Person test(){
                  Person user = new Person();
                  user.setRealName("不才陳某");
                  user.setPhoneNumber("19796328206");
                  user.setAddress("浙江省杭州市溫州市....");
                  user.setIdCard("4333333333334334333");
                  return user;
              }
          }

          調(diào)用接口查看數(shù)據(jù)有沒(méi)有正常脫敏,結(jié)果如下:

          {
              "realName""不*陳某",
              "address""浙江省****市溫州市..****",
              "phoneNumber""197****8206",
              "idCard""4333****34333"
          }

          6. 總結(jié)

          數(shù)據(jù)脫敏有很多種實(shí)現(xiàn)方式,關(guān)鍵是哪種更加適合,哪種更加優(yōu)雅.....

          四、日志文件如何數(shù)據(jù)脫敏?

          上面講了配置文件、接口返回值的數(shù)據(jù)脫敏,現(xiàn)在總該輪到日志脫敏了。項(xiàng)目中總避免不了打印日志,肯定會(huì)涉及到一些敏感數(shù)據(jù)被明文打印出來(lái),那么此時(shí)就需要過(guò)濾掉這些敏感數(shù)據(jù)(身份證、號(hào)碼、用戶名.....)。

          下面以log4j2這款日志為例講解一下日志如何脫敏,其他日志框架大致思路一樣。

          1. 添加log4j2日志依賴

          Spring Boot 默認(rèn)日志框架是logback,但是我們可以切換到log4j2,依賴如下:

          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
              <!-- 去掉springboot默認(rèn)配置 -->
              <exclusions>
                  <exclusion>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-logging</artifactId>
                  </exclusion>
              </exclusions>
          </dependency>
          <!--使用log4j2替換 LogBack-->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-log4j2</artifactId>
          </dependency>

          2. 在/resource目錄下新建log4j2.xml配置

          log4j2的日志配置很簡(jiǎn)單,只需要在/resource文件夾下新建一個(gè)log4j2.xml配置文件,內(nèi)容如下圖:

          關(guān)于每個(gè)節(jié)點(diǎn)如何配置,含義是什么,在我上面的兩篇文章中有詳細(xì)的介紹。

          上圖的配置并沒(méi)有實(shí)現(xiàn)數(shù)據(jù)脫敏,這是普通的配置,使用的是PatternLayout

          3.  自定義PatternLayout實(shí)現(xiàn)數(shù)據(jù)脫敏

          步驟2中的配置使用的是PatternLayout實(shí)現(xiàn)日志的格式,那么我們也可以自定義一個(gè)PatternLayout來(lái)實(shí)現(xiàn)日志的過(guò)濾脫敏。

          PatternLayout的類圖繼承關(guān)系如下:

          從上圖中可以清楚的看出來(lái),PatternLayout繼承了一個(gè)抽象類AbstractStringLayout,因此想要自定義只需要繼承這個(gè)抽象類即可。

          1、創(chuàng)建CustomPatternLayout,繼承抽象類AbstractStringLayout

          代碼如下:

          /**
           * log4j2 脫敏插件
           * 繼承AbstractStringLayout
           **/

          @Plugin(name = "CustomPatternLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
          public class CustomPatternLayout extends AbstractStringLayout {


              public final static Logger logger = LoggerFactory.getLogger(CustomPatternLayout.class);
              private PatternLayout patternLayout;


              protected CustomPatternLayout(Charset charset, String pattern) {
                  super(charset);
                  patternLayout = PatternLayout.newBuilder().withPattern(pattern).build();
                  initRule();
              }

              /**
               * 要匹配的正則表達(dá)式map
               */

              private static Map<String, Pattern> REG_PATTERN_MAP = new HashMap<>();
              private static Map<String, String> KEY_REG_MAP = new HashMap<>();


              private void initRule() {
                  try {
                      if (MapUtils.isEmpty(Log4j2Rule.regularMap)) {
                          return;
                      }
                      Log4j2Rule.regularMap.forEach((a, b) -> {
                          if (StringUtils.isNotBlank(a)) {
                              Map<String, String> collect = Arrays.stream(a.split(",")).collect(Collectors.toMap(c -> c, w -> b, (key1, key2) -> key1));
                              KEY_REG_MAP.putAll(collect);
                          }
                          Pattern compile = Pattern.compile(b);
                          REG_PATTERN_MAP.put(b, compile);
                      });

                  } catch (Exception e) {
                      logger.info(">>>>>> 初始化日志脫敏規(guī)則失敗 ERROR:{}", e);
                  }

              }

              /**
               * 處理日志信息,進(jìn)行脫敏
               * 1.判斷配置文件中是否已經(jīng)配置需要脫敏字段
               * 2.判斷內(nèi)容是否有需要脫敏的敏感信息
               * 2.1 沒(méi)有需要脫敏信息直接返回
               * 2.2 處理: 身份證 ,姓名,手機(jī)號(hào)敏感信息
               */

              public String hideMarkLog(String logStr) {
                  try {
                      //1.判斷配置文件中是否已經(jīng)配置需要脫敏字段
                      if (StringUtils.isBlank(logStr) || MapUtils.isEmpty(KEY_REG_MAP) || MapUtils.isEmpty(REG_PATTERN_MAP)) {
                          return logStr;
                      }
                      //2.判斷內(nèi)容是否有需要脫敏的敏感信息
                      Set<String> charKeys = KEY_REG_MAP.keySet();
                      for (String key : charKeys) {
                          if (logStr.contains(key)) {
                              String regExp = KEY_REG_MAP.get(key);
                              logStr = matchingAndEncrypt(logStr, regExp, key);
                          }
                      }
                      return logStr;
                  } catch (Exception e) {
                      logger.info(">>>>>>>>> 脫敏處理異常 ERROR:{}", e);
                      //如果拋出異常為了不影響流程,直接返回原信息
                      return logStr;
                  }
              }

              /**
               * 正則匹配對(duì)應(yīng)的對(duì)象。
               *
               * @param msg
               * @param regExp
               * @return
               */

              private static String matchingAndEncrypt(String msg, String regExp, String key) {
                  Pattern pattern = REG_PATTERN_MAP.get(regExp);
                  if (pattern == null) {
                      logger.info(">>> logger 沒(méi)有匹配到對(duì)應(yīng)的正則表達(dá)式 ");
                      return msg;
                  }
                  Matcher matcher = pattern.matcher(msg);
                  int length = key.length() + 5;
                  boolean contains = Log4j2Rule.USER_NAME_STR.contains(key);
                  String hiddenStr = "";
                  while (matcher.find()) {
                      String originStr = matcher.group();
                      if (contains) {
                          // 計(jì)算關(guān)鍵詞和需要脫敏詞的距離小于5。
                          int i = msg.indexOf(originStr);
                          if (i < 0) {
                              continue;
                          }
                          int span = i - length;
                          int startIndex = span >= 0 ? span : 0;
                          String substring = msg.substring(startIndex, i);
                          if (StringUtils.isBlank(substring) ||  !substring.contains(key)) {
                              continue;
                          }
                          hiddenStr = hideMarkStr(originStr);
                          msg = msg.replace(originStr, hiddenStr);
                      } else {
                          hiddenStr = hideMarkStr(originStr);
                          msg = msg.replace(originStr, hiddenStr);
                      }

                  }
                  return msg;
              }

              /**
               * 標(biāo)記敏感文字規(guī)則
               *
               * @param needHideMark
               * @return
               */

              private static String hideMarkStr(String needHideMark) {
                  if (StringUtils.isBlank(needHideMark)) {
                      return "";
                  }
                  int startSize = 0, endSize = 0, mark = 0, length = needHideMark.length();

                  StringBuffer hideRegBuffer = new StringBuffer("(\\S{");
                  StringBuffer replaceSb = new StringBuffer("$1");

                  if (length > 4) {
                      int i = length / 3;
                      startSize = i;
                      endSize = i;
                  } else {
                      startSize = 1;
                      endSize = 0;
                  }

                  mark = length - startSize - endSize;
                  for (int i = 0; i < mark; i++) {
                      replaceSb.append("*");
                  }
                  hideRegBuffer.append(startSize).append("})\\S*(\\S{").append(endSize).append("})");
                  replaceSb.append("$2");
                  needHideMark = needHideMark.replaceAll(hideRegBuffer.toString(), replaceSb.toString());
                  return needHideMark;
              }


              /**
               * 創(chuàng)建插件
               */

              @PluginFactory
              public static Layout createLayout(@PluginAttribute(value = "pattern") final String pattern,
                                                @PluginAttribute(value = "charset") final Charset charset) 
          {
                  return new CustomPatternLayout(charset, pattern);
              }


              @Override
              public String toSerializable(LogEvent event) {
                  return hideMarkLog(patternLayout.toSerializable(event));
              }

          }

          關(guān)于其中的一些細(xì)節(jié),比如@Plugin@PluginFactory這兩個(gè)注解什么意思?log4j2如何實(shí)現(xiàn)自定義一個(gè)插件,這里不再詳細(xì)介紹,不是本文重點(diǎn),有興趣的可以查看log4j2的官方文檔。

          2、自定義自己的脫敏規(guī)則

          上述代碼中的Log4j2Rule則是脫敏規(guī)則靜態(tài)類,我這里是直接放在了靜態(tài)類中配置,實(shí)際項(xiàng)目中可以設(shè)置到配置文件中,代碼如下:

          /**
           * 現(xiàn)在攔截加密的日志有三類:
           * 1,身份證
           * 2,姓名
           * 3,身份證號(hào)
           * 加密的規(guī)則后續(xù)可以優(yōu)化在配置文件中
           **/

          public class Log4j2Rule {

              /**
               * 正則匹配 關(guān)鍵詞 類別
               */

              public static Map<String, String> regularMap = new HashMap<>();
              /**
               * TODO  可配置
               * 此項(xiàng)可以后期放在配置項(xiàng)中
               */

              public static final String USER_NAME_STR = "Name,name,聯(lián)系人,姓名";
              public static final String USER_IDCARD_STR = "empCard,idCard,身份證,證件號(hào)";
              public static final String USER_PHONE_STR = "mobile,Phone,phone,電話,手機(jī)";

              /**
               * 正則匹配,自己根據(jù)業(yè)務(wù)要求自定義
               */

              private static String IDCARD_REGEXP = "(\\d{17}[0-9Xx]|\\d{14}[0-9Xx])";
              private static String USERNAME_REGEXP = "[\\u4e00-\\u9fa5]{2,4}";
              private static String PHONE_REGEXP = "(?<!\\d)(?:(?:1[3456789]\\d{9})|(?:861[356789]\\d{9}))(?!\\d)";

              static {
                  regularMap.put(USER_NAME_STR, USERNAME_REGEXP);
                  regularMap.put(USER_IDCARD_STR, IDCARD_REGEXP);
                  regularMap.put(USER_PHONE_STR, PHONE_REGEXP);
              }

          }

          經(jīng)過(guò)上述兩個(gè)步驟,自定義的PatternLayout已經(jīng)完成,下面將是改寫log4j2.xml這個(gè)配置文件了。

          4. 修改log4j2.xml配置文件

          其實(shí)這里修改很簡(jiǎn)單,原配置文件是直接使用PatternLayout進(jìn)行日志格式化的,那么只需要將默認(rèn)的<PatternLayout/>這個(gè)節(jié)點(diǎn)替換成<CustomPatternLayout/>,如下圖:

          直接全局替換掉即可,至此,這個(gè)配置文件就修改完成了。

          5. 演示效果

          步驟3這邊自定義了脫敏規(guī)則靜態(tài)類Log4j2Rule,其中定義了姓名、身份證、號(hào)碼這三個(gè)脫敏規(guī)則,如下:

          下面就來(lái)演示這三個(gè)規(guī)則能否正確脫敏,直接使用日志打印,代碼如下:

          @Test
          public void test3(){
           log.debug("身份證:{},姓名:{},電話:{}","320829112334566767","不才陳某","19896327106");
          }

          控制臺(tái)打印的日志如下:

          身份證:320829******566767,姓名:不***,電話:198*****106

          哦豁,成功了,so easy?。?!

          6. 總結(jié)

          日志脫敏的方案很多,陳某也只是介紹一種常用的,有興趣的可以研究一下。

          五、總結(jié)

          本篇文章從三個(gè)維度介紹了隱私數(shù)據(jù)的脫敏實(shí)現(xiàn)方案,碼字不易,趕緊點(diǎn)贊收藏吧?。?!

          源碼地址:

          https://github.com/chenjiabing666/JavaFamily/tree/master/springboot-jasypt


          1. Spring Boot 集成 JUnit5,更優(yōu)雅單元測(cè)試!

          2. 常見(jiàn)算法復(fù)雜度速查表,速度收藏!

          3. Redis的這些拓展方案

          4. 干掉SQL中的like,我用es后運(yùn)營(yíng)小姐姐們都說(shuō)好快!

          最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊(cè),覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點(diǎn)“在看”,關(guān)注公眾號(hào)并回復(fù) Java 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          文章有幫助的話,在看,轉(zhuǎn)發(fā)吧。

          謝謝支持喲 (*^__^*)

          瀏覽 90
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  狠狠搞狠狠操 | 天天躁日日躁人妻久久澡 | 中文字幕亚洲欧美日韩高 | 亚洲区色图欧美 | 五月丁香综合婷婷 |