【问题标题】:Logback configuration to mask specific log data用于屏蔽特定日志数据的 Logback 配置
【发布时间】:2018-11-07 13:29:47
【问题描述】:

我有一个 Spring Boot Web 应用程序,并且正在使用 logback 作为我的日志记录解决方案。我一直在查看文档,但找不到一种简单或“正确”的方式来掩盖私人/特定数据(个人信息、信用卡号等)。

我能找到的最接近的是 Logback 过滤器,但是围绕这些过滤器的用例似乎更多是关于省略符合特定条件的日志,我只是想屏蔽所有应用程序范围的日志。

这似乎是一个基本的问题,我敢肯定我错过了一些超级基本的东西,但是非常感谢任何推动或指向正确方向的东西。

我也没有被锁定在 logback 中,所以如果有一个更简单/更好的方法可以使用 log4j2 来做到这一点,例如,我全神贯注

【问题讨论】:

标签: java spring logging logback


【解决方案1】:

要屏蔽可配置字段,您需要创建MaskingPatternLayout,如下所示,

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.spi.ILoggingEvent;

public class MaskingPatternLayout extends PatternLayout {

  private String patternsProperty;
  private Optional<Pattern> pattern;

  public String getPatternsProperty() {
    return patternsProperty;
  }

  public void setPatternsProperty(String patternsProperty) {
    this.patternsProperty = patternsProperty;
    if (this.patternsProperty != null) {
      this.pattern = Optional.of(Pattern.compile(patternsProperty, Pattern.MULTILINE));
    } else {
      this.pattern = Optional.empty();
    }
  }

  @Override
  public String doLayout(ILoggingEvent event) {
    final StringBuilder message = new StringBuilder(super.doLayout(event));

    if (pattern.isPresent()) {
      Matcher matcher = pattern.get().matcher(message);
      while (matcher.find()) {

        int group = 1;
        while (group <= matcher.groupCount()) {
          if (matcher.group(group) != null) {
            final int startGrpIndex = matcher.start(group);
            final int endGrpIndex = matcher.end(group);
            final int diff = endGrpIndex - startGrpIndex + 1;
            int startIndex = startGrpIndex + diff;
            final int endIndex1 = message.indexOf(",", startIndex);
            final int endIndex2 = message.indexOf(" ", startIndex);
            final int endIndex3 = message.indexOf(")", startIndex);
            final int endIndex4 = message.indexOf("\n", startIndex);

            final Integer endIndex = getSmallestInt(
              Arrays.asList(Integer.valueOf(endIndex1), Integer.valueOf(endIndex2), Integer.valueOf(endIndex3), Integer.valueOf(endIndex4)));
            if (endIndex == null || endIndex <= 0) {
              continue;
            }

            for (int i = startIndex; i < endIndex; i++) {
              message.setCharAt(i, '*');
            }
          }
          group++;
        }
      }
    }
    return message.toString();
  }

  private Integer getSmallestInt(List<Integer> integerList) {

    return integerList.stream().filter(integer -> integer > 0).reduce((x, y) -> x < y ? x : y).get();
  }

}

需要在 logback.xml appenders 中添加编码器 -

<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
      <layout class="com.adgiants.config.MaskingPatternLayout">
        <patternsProperty>(password)|(email)</patternsProperty>
        <pattern>%d [%thread] %-5level %logger{35} - %msg%n</pattern>
      </layout>
</encoder>

此配置将扫描您的所有日志语句并匹配“密码”或“电子邮件”之类的词(无论您在 logback.xml 编码器中配置了哪个),其值将被替换为 ****

例如

log.info("Received sign-up request, password=DummyPassword@123");

在日志中,上面的语句将显示为,

Received sign-up request, password=*****************

【讨论】:

  • 如何屏蔽具有数组的对象? companyName=test 私人公司, eventType=new, loginIds=[1334566, 795455, 4549554],
猜你喜欢
  • 2022-11-07
  • 1970-01-01
  • 2011-06-04
  • 1970-01-01
  • 1970-01-01
  • 2014-03-03
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多