在 Spring 启动中使用 MDC 或任何过滤器屏蔽日志消息中的密码,而无需使用 logback.xml 文件



我必须在不使用 logback.xml 文件的情况下屏蔽日志消息中的密码 春天启动。

示例日志: LOGGER.info("用户密码 : {}", pwd(;

预期输出: 2019-11-26 18:27:15,951 [http-nio-8080-exec-2] INFO com.test.controller.TestController - 用户密码:***********

我能够使用logback.xml文件实现相同的效果。 如下所示。 但是没有回程文件需要在 Spring 启动中使用 application.properties 配置文件。

注意:不要使用 log4j xml 文件。 我们应该使用 slf4j 或 MDC 或任何过滤器和 application.properties

<configuration>
<property name="DEV_HOME" value="c:/logs" />
<appender name="CONSOLE"
class="ch.qos.logback.core.ConsoleAppender">
<encoder
class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="com.test.config.MaskingPatternLayout">
<patternsProperty>(SSN)</patternsProperty>
<pattern>%d [%thread] %-5level %logger{35} - %msg%n</pattern>
</layout>
</encoder>
</appender>
<logger name="com.test" level="debug" additivity="false">
<appender-ref ref="CONSOLE" />
</logger>
<root level="error">
<appender-ref ref="CONSOLE" />
</root>
</configuration>

是否可以在不使用 logback.xml 文件和 log4j.xml 文件的情况下实现这一点?

我们是否可以在应用程序属性文件中提及模式布局 Java 类,而不是在 logback.xml 文件中提及相同的类? " 在上面的例子中,我提到了 logback 中的 java 文件">

添加了遮罩模式布局以供参考:

package com.test.config;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.stereotype.Component;
import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.spi.ILoggingEvent;
@Component
public class MaskingPatternTest 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) {
for (int i = matcher.start(group); i < matcher.end(group); i++) {
message.setCharAt(i, '*');
}
}
group++;
}
}
}
return message.toString();
}
}

请帮忙。

一旦你想使用高级日志记录功能(除了设置日志级别(,你必须使用特定于日志记录库的配置,例如logback.xml用于 Logback,log4j.xml用于 log4j 等。

但是,Logback 确实有一个可以调用的 API。例如,您可以使用 bean 设置ConsoleAppender

@Bean
public LoggerContext loggerContext() {
return (LoggerContext) LoggerFactory.getILoggerFactory();
}
@Bean
public MaskPatternLayout maskPatternLayout(LoggerContext context) {
MaskPatternLayout layout = new MaskPatternLayout();
layout.setPatternsProperty("(SSN)");
layout.setPattern("%d [%thread] %-5level %logger{35} - %msg%n");
layout.setContext(context);
layout.start();
return layout;
}
@Bean
public LayoutWrappingEncoder<ILoggingEvent> maskEncoder(MaskPatternLayout layout) {
LayoutWrappingEncoder<ILoggingEvent> encoder = new LayoutWrappingEncoder<>();
encoder.setLayout(layout);
return encoder;
}
@Bean
public ConsoleAppender<ILoggingEvent> maskConsoleAppender(LoggerContext context, LayoutWrappingEncoder<ILoggingEvent> maskEncoder) {
ConsoleAppender<ILoggingEvent> appender = new ConsoleAppender<>();
appender.setContext(context);
appender.setEncoder(maskEncoder);
appender.start();
return appender;
}

现在您可以创建自己的LoggerFactory

@Component
public class MaskLoggerFactory {
private final Appender<ILoggingEvent> appender;
public MaskLoggerFactory(Appender<ILoggingEvent> appender) {
this.appender = appender;
}
public org.slf4j.Logger getLogger(String name) {
Logger logger = (Logger) LoggerFactory.getLogger(name);
logger.addAppender(appender);
logger.setLevel(Level.ALL);
logger.setAdditive(false);
return logger;
}
public org.slf4j.Logger getLogger(Class<?> cls) {
return getLogger(cls.getName());
}
}

之后,您可以自动MaskLoggerFactory线以获得适当的Logger。但是,这并不能使事情更易于使用,如果您的唯一理由是避免创建单独的 XML 文件,我鼓励您继续使用该 XML 文件。

最新更新