如何实现Log4j日志中敏感字段的分类与过滤实例?

2026-04-30 09:062阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2167个文字,预计阅读时间需要9分钟。

如何实现Log4j日志中敏感字段的分类与过滤实例?

项目上线时,需要对项目进行安全检查,其中有两项是:对输出日志进行分类和过滤掉日志中敏感字段的日志。

项目使用Log4j日志系统,以下简单介绍如何实现这两项要求:

1. 日志分类: - 使用Log4j的`PatternLayout`设置日志格式,通过定义不同的日志级别,将日志分类输出。 - 例如,可以将INFO级别的日志输出到info.log文件,ERROR级别的日志输出到error.log文件。

2. 过滤敏感字段: - 通过自定义Log4j的`PatternLayout`或使用`LogFilter`来过滤掉日志中的敏感信息。 - 例如,可以使用正则表达式匹配并替换掉敏感字段,如用户名、密码等。

如何实现Log4j日志中敏感字段的分类与过滤实例?

实现示例:

javaimport org.apache.log4j.PatternLayout;import org.apache.log4j.RollingFileAppender;

public class LogConfig { public static void configureLogger() { // 创建PatternLayout PatternLayout layout=new PatternLayout(%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n);

// 创建RollingFileAppender RollingFileAppender rollingFileAppender=new RollingFileAppender(layout, logs/app.log);

// 设置日志级别和文件大小限制 rollingFileAppender.setThreshold(Priority.INFO); rollingFileAppender.setMaxFileSize(10MB); rollingFileAppender.setMaxBackupIndex(5);

// 过滤敏感信息 rollingFileAppender.addFilter(new LogFilter());

// 添加Appender到Logger Logger logger=Logger.getLogger(LogConfig.class); logger.addAppender(rollingFileAppender); }

// LogFilter类,用于过滤敏感信息 static class LogFilter extends Filter { @Override public FilterReply decide(LoggingEvent event) { String message=event.getMessage().toString(); // 使用正则表达式替换敏感信息 message=message.replaceAll((?i)password, **); event.setMessage(new SimpleLayout().format(event)); return FilterReply.NEUTRAL; } }}

通过以上配置,可以实现日志分类和过滤敏感信息的功能。

项目上线时,需要对项目做安全检查,其中有两项是对输出日志进行分类和过滤掉日志中敏感字段。

项目使用Log4j日志系统,下面简单介绍下这两项要求的实现方式。

对日志进行分类,要求调用其他服务的API日志按照格式单独输出到一个文件。

方式: 除根Logger外,再额外增加一个apiLogger,如下,

<!-- api logger的设置--> <logger name="log4j.logger.apiLogger" additivity="false"> <level value ="INFO"/> <appender-ref ref="apiConsoleAppender"/> <appender-ref ref="apiMsgOutGoingAppender"/> </logger> <!-- 根logger的设置--> <root> <level value ="INFO"/> <appender-ref ref="ConsoleAppender"/> <appender-ref ref="DailyRollingFileAppender"/> </root>

注: (1) additivity设为false,则root中的配置就失效了。即使用root配置的日志不会在apiLogger的文件中出现;

(2) 每种logger指定两个appender,分别是在debug console和Linux 服务器日志文件中显示。

根日志的ConsoleAppender和DailyRollingFileAppender的配置如下:

<appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender"> <!-- 设置日志输出的样式 --> <layout class="org.apache.log4j.PatternLayout"> <!-- 设置日志输出的格式 --> <param name="ConversionPattern" value="**** [%p] [%d{yyyy/MM/dd HH:mm:ss:SSS}] ******************************%n[Thread] %t%n[Class] %C%n[Method] %M%n[Message] %m%n%n" /> </layout> </appender>

<appender name="DailyRollingFileAppender" class="org.apache.log4j.DailyRollingFileAppender"> <!-- 设置日志信息输出文件全路径名 --> <param name="File" value="/var/log/tomcat/hpc.log" /> <!-- 设置日志多久回滚一次,即产生一个新的日志文件 --> <param name="DatePattern" value="'_'yyyy-MM-dd" /> <!--日志编码格式--> <param name="Encoding" value="UTF-8" /> <!-- 设置是否在重新启动服务时,在原有日志的基础添加新日志 --> <param name="Append" value="true" /> <!-- 设置日志输出的样式 --> <layout class="org.apache.log4j.PatternLayout"> <!-- 设置日志输出的格式 --> <param name="ConversionPattern" value="**** [%p] [%d{yyyy/MM/dd HH:mm:ss:SSS}] *************************%n[Thread] %t%n[Class] %C%n[Method] %M%n[Message] %m%n%n" /> </layout> <!-- 日志过滤: adminPass, X-Auth-Token; 包含该字符串的信息不输出 --> <filter class="org.apache.log4j.varia.StringMatchFilter"> <param name="StringToMatch" value="adminPass" /> <param name="AcceptOnMatch" value="false" /> </filter> <filter class="org.apache.log4j.varia.StringMatchFilter"> <param name="StringToMatch" value="X-Auth-Token" /> <param name="AcceptOnMatch" value="false" /> </filter> <filter class="org.apache.log4j.varia.StringMatchFilter"> <param name="StringToMatch" value="PW" /> <param name="AcceptOnMatch" value="false" /> </filter> <filter class="org.apache.log4j.varia.StringMatchFilter"> <param name="StringToMatch" value="pwd" /> <param name="AcceptOnMatch" value="false" /> </filter> <!-- password Password--> <filter class="org.apache.log4j.varia.StringMatchFilter"> <param name="StringToMatch" value="assword" /> <param name="AcceptOnMatch" value="false" /> </filter> <!-- 过滤pstmt-, 所有的数据库操作均包含此字符串--> <filter class="org.apache.log4j.varia.StringMatchFilter"> <param name="StringToMatch" value="pstmt-" /> <param name="AcceptOnMatch" value="false" /> </filter> </appender>

apiLogger的apiConsoleAppender和apiMsgOutGoingAppender设置如下:

<!-- 将日志信息输出到文件,可以配置多久产生一个新的日志信息文件 --> <appender name="apiConsoleAppender" class="org.apache.log4j.ConsoleAppender"> <!-- 设置日志输出的样式 --> <layout class="org.apache.log4j.PatternLayout"> <!-- 设置日志输出的格式 --> <param name="ConversionPattern" value='[%-5p] [Outgoing] %X{og.serverIp} [%d{yyyy-MM-dd HH:mm:ss,SSS z}] %X{og.respTime} "%X{og.visitUri}" %X{og.statusCode} %X{og.reqLen} %X{og.respLen} %n' /> </layout> </appender>

<appender name="apiMsgOutGoingAppender" class="org.apache.log4j.RollingFileAppender"> <!-- 设置日志信息输出文件全路径名 --> <param name="File" value="/var/log/tomcat/interface.log" /> <!--日志编码格式--> <param name="Encoding" value="UTF-8" /> <!-- 设置是否在重新启动服务时,在原有日志的基础添加新日志 --> <param name="Append" value="true" /> <!-- 设置文件最大size --> <param name="MaxFileSize" value="30MB" /> <!-- 保留日志文件数的最大值 --> <param name="MaxBackupIndex" value="100" /> <!-- 设置日志输出的样式 --> <layout class="org.apache.log4j.PatternLayout"> <!-- 设置日志输出的格式 --> <param name="ConversionPattern" value='[%-5p] [Outgoing] %X{og.serverIp} [%d{yyyy-MM-dd HH:mm:ss,SSS z}] %X{og.respTime} "%X{og.visitUri}" %X{og.statusCode} %X{og.reqLen} %X{og.respLen} %n'/> </layout> </appender>

注:(1) Log4j系统Appender组件负责日志的输出配置,包括输出目录,最大输出大小,输出文件数等;Layout组件负责日志输出的格式。

(2)JAVA代码在使用日志系统时,默认用根日志的配置输出,若想使用apiLogger,使用:

private static Logger log = Logger.getLogger("log4j.logger.apiLogger");

(3)日志layout中传入自定义参数,使用MDC类:

public static void configAndPrintAPILogger(Logger logger, int statusCode, String method, String url, long responseTime, int requestLength, int responseLength) { String endpoint = url.split("/")[2]; MDC.put("og.serverIp", endpoint); MDC.put("og.respTime", responseTime); //截取 endpoint之后的 MDC.put("og.visitUri", method + " " + url.substring(8 + endpoint.length())); MDC.put("og.statusCode", statusCode); MDC.put("og.reqLen", requestLength); MDC.put("og.respLen", responseLength); logger.info(""); }

经上述配置后,日志的输出如下:

2. 日志中过滤敏感字符,如password, PW, adminPass等。如DailyRollingFileAppender中所示,使用StringMatchFilter:

<!-- 过滤password Password--> <filter class="org.apache.log4j.varia.StringMatchFilter"> <param name="StringToMatch" value="assword" /> <param name="AcceptOnMatch" value="false" /> </filter>

StringMatchFilter中使用msg.indexOf(StringToMatch)参数判断是否过滤,即该条日志包含指定字段,若AcceptOnMatch设置为false,则不输出。

需要注意的是,log4j日志系统采用xml格式时才能用该种方式过滤,properties格式时不能用此方法。

补充知识:解决日志log4j,slf4j,logback冲突问题

问题描述:

启动tomcat,发现tomcat无法启动,catalina.out有如下错误日志:

INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.listenerStop Exception sending context destroyed event to listener instance of class org.springframework.web.context.ContextLoaderListener java.lang.NoClassDefFoundError: Could not initialize class org.apache.log4j.Log4jLoggerFactory at org.apache.log4j.LogManager.getLogger(LogManager.java:44) at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:73) at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:270) at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:156) at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:132) at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:274) at org.springframework.web.context.ContextCleanupListener.<clinit>(ContextCleanupListener.java:43) at org.springframework.web.context.ContextLoaderListener.contextDestroyed(ContextLoaderListener.java:145) at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4860) at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5495) at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:224) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:159) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1407) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1397) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)

问题分析:

检查lib库下面,发现今天更新过log4j和logback组合,总共有如下包:

slf4j-api-1.7.5.jar

slf4j-log4j12-1.6.1.jar

log4j-1.2.16.jar

log4j-over-slf4j-1.7.5.jar

logback-core-1.1.2.jar

logback-classic-1.1.2.jar

通过查询资料发现,包slf4j-log4j12-1.6.1.jar 和log4j有冲突。

解决方法:

删除后正常,删除这个:slf4j-log4j12-1.6.1.jar

附件常见组合:

log4j+slf4j

slf4j-api-1.7.5.jar

slf4j-log4j12-1.6.1.jar

log4j-1.2.16.jar

slf4j+logback

logback-core-1.1.2.jar

logback-classic-1.1.2.jar

slf4j-api-1.7.5.jar

以上这篇Log4j日志分类和过滤敏感字段的实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持易盾网络。

标签:实例

本文共计2167个文字,预计阅读时间需要9分钟。

如何实现Log4j日志中敏感字段的分类与过滤实例?

项目上线时,需要对项目进行安全检查,其中有两项是:对输出日志进行分类和过滤掉日志中敏感字段的日志。

项目使用Log4j日志系统,以下简单介绍如何实现这两项要求:

1. 日志分类: - 使用Log4j的`PatternLayout`设置日志格式,通过定义不同的日志级别,将日志分类输出。 - 例如,可以将INFO级别的日志输出到info.log文件,ERROR级别的日志输出到error.log文件。

2. 过滤敏感字段: - 通过自定义Log4j的`PatternLayout`或使用`LogFilter`来过滤掉日志中的敏感信息。 - 例如,可以使用正则表达式匹配并替换掉敏感字段,如用户名、密码等。

如何实现Log4j日志中敏感字段的分类与过滤实例?

实现示例:

javaimport org.apache.log4j.PatternLayout;import org.apache.log4j.RollingFileAppender;

public class LogConfig { public static void configureLogger() { // 创建PatternLayout PatternLayout layout=new PatternLayout(%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n);

// 创建RollingFileAppender RollingFileAppender rollingFileAppender=new RollingFileAppender(layout, logs/app.log);

// 设置日志级别和文件大小限制 rollingFileAppender.setThreshold(Priority.INFO); rollingFileAppender.setMaxFileSize(10MB); rollingFileAppender.setMaxBackupIndex(5);

// 过滤敏感信息 rollingFileAppender.addFilter(new LogFilter());

// 添加Appender到Logger Logger logger=Logger.getLogger(LogConfig.class); logger.addAppender(rollingFileAppender); }

// LogFilter类,用于过滤敏感信息 static class LogFilter extends Filter { @Override public FilterReply decide(LoggingEvent event) { String message=event.getMessage().toString(); // 使用正则表达式替换敏感信息 message=message.replaceAll((?i)password, **); event.setMessage(new SimpleLayout().format(event)); return FilterReply.NEUTRAL; } }}

通过以上配置,可以实现日志分类和过滤敏感信息的功能。

项目上线时,需要对项目做安全检查,其中有两项是对输出日志进行分类和过滤掉日志中敏感字段。

项目使用Log4j日志系统,下面简单介绍下这两项要求的实现方式。

对日志进行分类,要求调用其他服务的API日志按照格式单独输出到一个文件。

方式: 除根Logger外,再额外增加一个apiLogger,如下,

<!-- api logger的设置--> <logger name="log4j.logger.apiLogger" additivity="false"> <level value ="INFO"/> <appender-ref ref="apiConsoleAppender"/> <appender-ref ref="apiMsgOutGoingAppender"/> </logger> <!-- 根logger的设置--> <root> <level value ="INFO"/> <appender-ref ref="ConsoleAppender"/> <appender-ref ref="DailyRollingFileAppender"/> </root>

注: (1) additivity设为false,则root中的配置就失效了。即使用root配置的日志不会在apiLogger的文件中出现;

(2) 每种logger指定两个appender,分别是在debug console和Linux 服务器日志文件中显示。

根日志的ConsoleAppender和DailyRollingFileAppender的配置如下:

<appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender"> <!-- 设置日志输出的样式 --> <layout class="org.apache.log4j.PatternLayout"> <!-- 设置日志输出的格式 --> <param name="ConversionPattern" value="**** [%p] [%d{yyyy/MM/dd HH:mm:ss:SSS}] ******************************%n[Thread] %t%n[Class] %C%n[Method] %M%n[Message] %m%n%n" /> </layout> </appender>

<appender name="DailyRollingFileAppender" class="org.apache.log4j.DailyRollingFileAppender"> <!-- 设置日志信息输出文件全路径名 --> <param name="File" value="/var/log/tomcat/hpc.log" /> <!-- 设置日志多久回滚一次,即产生一个新的日志文件 --> <param name="DatePattern" value="'_'yyyy-MM-dd" /> <!--日志编码格式--> <param name="Encoding" value="UTF-8" /> <!-- 设置是否在重新启动服务时,在原有日志的基础添加新日志 --> <param name="Append" value="true" /> <!-- 设置日志输出的样式 --> <layout class="org.apache.log4j.PatternLayout"> <!-- 设置日志输出的格式 --> <param name="ConversionPattern" value="**** [%p] [%d{yyyy/MM/dd HH:mm:ss:SSS}] *************************%n[Thread] %t%n[Class] %C%n[Method] %M%n[Message] %m%n%n" /> </layout> <!-- 日志过滤: adminPass, X-Auth-Token; 包含该字符串的信息不输出 --> <filter class="org.apache.log4j.varia.StringMatchFilter"> <param name="StringToMatch" value="adminPass" /> <param name="AcceptOnMatch" value="false" /> </filter> <filter class="org.apache.log4j.varia.StringMatchFilter"> <param name="StringToMatch" value="X-Auth-Token" /> <param name="AcceptOnMatch" value="false" /> </filter> <filter class="org.apache.log4j.varia.StringMatchFilter"> <param name="StringToMatch" value="PW" /> <param name="AcceptOnMatch" value="false" /> </filter> <filter class="org.apache.log4j.varia.StringMatchFilter"> <param name="StringToMatch" value="pwd" /> <param name="AcceptOnMatch" value="false" /> </filter> <!-- password Password--> <filter class="org.apache.log4j.varia.StringMatchFilter"> <param name="StringToMatch" value="assword" /> <param name="AcceptOnMatch" value="false" /> </filter> <!-- 过滤pstmt-, 所有的数据库操作均包含此字符串--> <filter class="org.apache.log4j.varia.StringMatchFilter"> <param name="StringToMatch" value="pstmt-" /> <param name="AcceptOnMatch" value="false" /> </filter> </appender>

apiLogger的apiConsoleAppender和apiMsgOutGoingAppender设置如下:

<!-- 将日志信息输出到文件,可以配置多久产生一个新的日志信息文件 --> <appender name="apiConsoleAppender" class="org.apache.log4j.ConsoleAppender"> <!-- 设置日志输出的样式 --> <layout class="org.apache.log4j.PatternLayout"> <!-- 设置日志输出的格式 --> <param name="ConversionPattern" value='[%-5p] [Outgoing] %X{og.serverIp} [%d{yyyy-MM-dd HH:mm:ss,SSS z}] %X{og.respTime} "%X{og.visitUri}" %X{og.statusCode} %X{og.reqLen} %X{og.respLen} %n' /> </layout> </appender>

<appender name="apiMsgOutGoingAppender" class="org.apache.log4j.RollingFileAppender"> <!-- 设置日志信息输出文件全路径名 --> <param name="File" value="/var/log/tomcat/interface.log" /> <!--日志编码格式--> <param name="Encoding" value="UTF-8" /> <!-- 设置是否在重新启动服务时,在原有日志的基础添加新日志 --> <param name="Append" value="true" /> <!-- 设置文件最大size --> <param name="MaxFileSize" value="30MB" /> <!-- 保留日志文件数的最大值 --> <param name="MaxBackupIndex" value="100" /> <!-- 设置日志输出的样式 --> <layout class="org.apache.log4j.PatternLayout"> <!-- 设置日志输出的格式 --> <param name="ConversionPattern" value='[%-5p] [Outgoing] %X{og.serverIp} [%d{yyyy-MM-dd HH:mm:ss,SSS z}] %X{og.respTime} "%X{og.visitUri}" %X{og.statusCode} %X{og.reqLen} %X{og.respLen} %n'/> </layout> </appender>

注:(1) Log4j系统Appender组件负责日志的输出配置,包括输出目录,最大输出大小,输出文件数等;Layout组件负责日志输出的格式。

(2)JAVA代码在使用日志系统时,默认用根日志的配置输出,若想使用apiLogger,使用:

private static Logger log = Logger.getLogger("log4j.logger.apiLogger");

(3)日志layout中传入自定义参数,使用MDC类:

public static void configAndPrintAPILogger(Logger logger, int statusCode, String method, String url, long responseTime, int requestLength, int responseLength) { String endpoint = url.split("/")[2]; MDC.put("og.serverIp", endpoint); MDC.put("og.respTime", responseTime); //截取 endpoint之后的 MDC.put("og.visitUri", method + " " + url.substring(8 + endpoint.length())); MDC.put("og.statusCode", statusCode); MDC.put("og.reqLen", requestLength); MDC.put("og.respLen", responseLength); logger.info(""); }

经上述配置后,日志的输出如下:

2. 日志中过滤敏感字符,如password, PW, adminPass等。如DailyRollingFileAppender中所示,使用StringMatchFilter:

<!-- 过滤password Password--> <filter class="org.apache.log4j.varia.StringMatchFilter"> <param name="StringToMatch" value="assword" /> <param name="AcceptOnMatch" value="false" /> </filter>

StringMatchFilter中使用msg.indexOf(StringToMatch)参数判断是否过滤,即该条日志包含指定字段,若AcceptOnMatch设置为false,则不输出。

需要注意的是,log4j日志系统采用xml格式时才能用该种方式过滤,properties格式时不能用此方法。

补充知识:解决日志log4j,slf4j,logback冲突问题

问题描述:

启动tomcat,发现tomcat无法启动,catalina.out有如下错误日志:

INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.listenerStop Exception sending context destroyed event to listener instance of class org.springframework.web.context.ContextLoaderListener java.lang.NoClassDefFoundError: Could not initialize class org.apache.log4j.Log4jLoggerFactory at org.apache.log4j.LogManager.getLogger(LogManager.java:44) at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:73) at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:270) at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:156) at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:132) at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:274) at org.springframework.web.context.ContextCleanupListener.<clinit>(ContextCleanupListener.java:43) at org.springframework.web.context.ContextLoaderListener.contextDestroyed(ContextLoaderListener.java:145) at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4860) at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5495) at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:224) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:159) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1407) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1397) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)

问题分析:

检查lib库下面,发现今天更新过log4j和logback组合,总共有如下包:

slf4j-api-1.7.5.jar

slf4j-log4j12-1.6.1.jar

log4j-1.2.16.jar

log4j-over-slf4j-1.7.5.jar

logback-core-1.1.2.jar

logback-classic-1.1.2.jar

通过查询资料发现,包slf4j-log4j12-1.6.1.jar 和log4j有冲突。

解决方法:

删除后正常,删除这个:slf4j-log4j12-1.6.1.jar

附件常见组合:

log4j+slf4j

slf4j-api-1.7.5.jar

slf4j-log4j12-1.6.1.jar

log4j-1.2.16.jar

slf4j+logback

logback-core-1.1.2.jar

logback-classic-1.1.2.jar

slf4j-api-1.7.5.jar

以上这篇Log4j日志分类和过滤敏感字段的实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持易盾网络。

标签:实例