Log4j日誌分類和過濾敏感欄位的例項
專案上線時,需要對專案做安全檢查,其中有兩項是對輸出日誌進行分類和過濾掉日誌中敏感欄位。
專案使用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(""); }
經上述配置後,日誌的輸出如下:
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日誌分類和過濾敏感欄位的例項就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。