欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Log4j日志分类和过滤敏感字段的实例

程序员文章站 2022-09-29 21:17:54
项目上线时,需要对项目做安全检查,其中有两项是对输出日志进行分类和过滤掉日志中敏感字段。项目使用log4j日志系统,下面简单介绍下这两项要求的实现方式。对日志进行分类,要求调用其他服务的api日志按照...

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

项目使用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);
 //截取 https://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("");
 }

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

Log4j日志分类和过滤敏感字段的实例

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日志分类和过滤敏感字段的实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。