Reu*_*aul 5 logging tomcat7 tomcat-valve
是否可以将 AccessLogValve 配置为在将密码写入日志文件之前隐藏/替换密码?我对阀门不熟悉,也许有办法插入自定义过滤器/阀门?
创建一个单独的 maven 项目:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>filtered-access-log-valve</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>7.0.70</version>
</dependency>
</dependencies>
</project>
Run Code Online (Sandbox Code Playgroud)
FilteredAccessLogValve.java
package test;
import org.apache.catalina.valves.AccessLogValve;
public class FilteredAccessLogValve extends AccessLogValve {
@Override
public void log(String message) {
super.log(message.replaceAll("password=[^&]*", "password=***"));
}
}
Run Code Online (Sandbox Code Playgroud)从项目构建 jar 工件并将其复制到tomcat/lib/
在tomcat/conf/server.xml 中更改访问日志阀类
<Valve className="test.FilteredAccessLogValve" ...>
最后我来到了这个解决方案,因为它需要最少的 tomcat 配置。
<Valve>标记关闭默认访问日志阀。创建AdvancedAccessLogFilter类:
package your.package;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class AdvancedAccessLogFilter implements Filter {
private static final String PASSWORD_REGEX = "password=[^&]+";
private static final String PASSWORD_MASK = "password=***";
private FilterConfig filterConfig = null;
public void destroy() {
this.filterConfig = null;
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
if (filterConfig == null) {
return;
}
HttpServletRequest request = (HttpServletRequest) servletRequest;
String maskedPath = request.getRequestURI()
+ (request.getQueryString() == null ? "" : request.getQueryString().replaceAll(PASSWORD_REGEX, PASSWORD_MASK))
+ " "
+ request.getProtocol();
request.setAttribute("maskedPath", maskedPath);
chain.doFilter(request, servletResponse);
}
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
}
Run Code Online (Sandbox Code Playgroud)在项目的web.xml 中注册 servlet 过滤器:
<filter>
<filter-name>AdvancedAccessLogFilter</filter-name>
<filter-class>your.package.AdvancedAccessLogFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AdvancedAccessLogFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Run Code Online (Sandbox Code Playgroud)使用修改后的访问日志阀模式创建src/main/webapp/META-INF/context.xml:
<?xml version='1.0' encoding='utf-8'?>
<Context>
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<Valve
className='org.apache.catalina.valves.AccessLogValve'
directory='logs'
prefix='localhost_access_log.'
suffix='.txt'
pattern='%h %t %m "%{maskedPath}r" %s %b %D'
/>
</Context>
Run Code Online (Sandbox Code Playgroud)如果您想从 Spring 上下文自动装配一些 bean,请添加SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
到过滤器的init()方法中。