如何配置Tomcat AccessLogValve来隐藏密码?

时间:2013-05-22 18:28:33

标签: logging tomcat7 tomcat-valve

是否可以将AccessLogValve配置为在将密码写入日志文件之前隐藏/替换密码?我不熟悉阀门,也许有一种方法可以插入自定义过滤器/阀门?

3 个答案:

答案 0 :(得分:4)

自定义AccessLogValve类

的解决方案
  1. 创建一个单独的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>
    

    <强> 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=***"));
        }
    }
    
  2. 从项目构建jar工件并将其复制到 tomcat / lib /

  3. tomcat / conf / server.xml 中更改访问日志阀类

    <Valve className="test.FilteredAccessLogValve" ...>

  4. 使用servlet过滤器的另一种解决方案

    最后我来到这个解决方案,因为它需要最少的tomcat配置。

    1. tomcat / conf / context.xml 中,通过评论<Valve>标记来关闭默认访问日志阀。
    2. 创建 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;
          }        
      }
      
    3. 在项目的 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>
      
    4. 使用修改过的访问日志阀模式创建 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>
      
    5. 如果要从Spring上下文自动装配某些bean,请添加SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); 过滤器的init()方法。

答案 1 :(得分:0)

简单的答案是扩展AccessLogValve类并覆盖日志方法,使用String#replaceAll将所有出现的密码替换为“ * ”。

答案 2 :(得分:0)

在使用嵌入式 tomcat 服务器的 SAP/Hybris 项目之一中遇到了同样的问题。每当使用密码授予类型进行 oauth/令牌调用时,用户和 OAuth 客户端的机密信息都会以以下格式记录在访问日志中。

0:0:0:0:0:0:0:1 - - [31/Mar/2021:21:19:38 +0530] "POST /authorizationserver/oauth/token?client_id=trusted_client&client_secret=secret&grant_type=password&username=admin&password=nimda HTTP/1.1" 200 334 "-" "PostmanRuntime/7.24.1"

**使用自定义 AccessLogValve 类解决 **

  1. 创建一个独立的 Maven 项目。

  2. 更新 Pom.xml 如下

    4.0.0 过滤访问日志阀 过滤访问日志阀 0.0.1-快照 过滤访问日志阀 过滤访问日志阀用于自定义日志值 org.apache.tomcat tomcat-catalina 8.5.57 Maven 编译器插件 3.5.1 1.8 1.8 org.apache.maven.plugins Maven jar 插件 包裹 罐

  3. 在 src/main/java 中创建一个类作为 FilteredAccessLogValve,它扩展了 org.apache.catalina.valves 包中的 AccessLogValve。类如下所示。

包 org.apache.catalina.valves;

导入 java.io.CharArrayWriter; 导入 java.io.IOException;

public class FilteredAccessLogValve extends AccessLogValve {
    @Override
    public void log(CharArrayWriter message) {
        CharArrayWriter caw = new CharArrayWriter();
        try {
            caw.write(message.toString().replaceAll("password=[^&^ ]*", "password=***").replaceAll("client_secret=[^&^ ]*",
                    "client_secret=***"));
            super.log(caw);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            caw.close();
        }
    }
}
  1. 使用 mvn clean -> mvn compile -> mvn install 构建 Jar。从/target 文件夹复制filtered-access-log-valve-0.0.1-SNAPSHOT jar 并将其放在hybris/config/customize/platform/tomcat/lib 文件夹中。

  2. 查找所有 server.xml hybris/config/tcServer/conf 和 hybris/config/tomcat/conf 文件,并在其中将所有阀门类定义替换为新的 FilteredAccessLogValve 类下面

之前:

<Valve  className="org.apache.catalina.valves.AccessLogValve"
                    directory="${HYBRIS_LOG_DIR}/tomcat"
                    prefix="access."
                    suffix=".log"
                    pattern="combined"
          />

之后:

<Valve  className="org.apache.catalina.valves.FilteredAccessLogValve"
                    directory="${HYBRIS_LOG_DIR}/tomcat"
                    prefix="access."
                    suffix=".log"
                    pattern="combined"
          />
  1. 在平台中运行ant定制,然后构建并启动服务器。

  2. 现在日志看起来像下面这样

    0:0:0:0:0:0:0:1 - - [31/​​Mar/2021:21:19:38 +0530] "POST /authorizationserver/oauth/token?client_id=trusted_client&client_secret=&grant_type=password&username=admin&password= HTTP/1.1" 200 334 "-" "PostmanRuntime/7.24.1"