2015-07-10 62 views
0

我们使用Spring Security来保护我们的Spring Web应用程序。事实上,我们正在使用Spring社交认证过滤器。要实现它并不容易,但它现在可行,一切都很好。Spring安全,远程用户和Tomcat日志

唯一缺少的是用户名不会出现在Tomcat日志中。在Tomcat中,如果我使用良好的老式BASIC身份验证,登录的用户会很好地出现在日志中。这非常有帮助。我想知道哪个授权用户正在做某些事情,用于分析等。

我知道Tomcat根据httpServletRequest.getRemoteUser()记录用户。 Spring将用户信息存储为SecurityContextHolder.getSecurityContext()。getPrincipal()。

我环顾了Spring文档,它看起来像我需要将SecurityContextHolderAwareRequestFilter添加到链,它将包装HttpServletRequest并提供getSecurityContext()和其他方法的有用实现。

我试图将它添加到我的Java SecurityConfiguration类,像这样:

@Override 
    protected void configure(HttpSecurity httpSecurity) throws Exception { 
     httpSecurity 
       .addFilter(new SecurityContextHolderAwareRequestFilter()) 

,但是当我这样做,我得到一个异常:

java.lang.NullPointerException 
    org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45) 

我可以清楚地看到是怎么回事上。在该SecurityContextHolderAwareRequestFilter线,它是:

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 
     throws IOException, ServletException { 
chain.doFilter(requestFactory.create((HttpServletRequest)req, (HttpServletResponse) res), res); 
} 

要么链参数为空(不可能)或requestFactory构件为空。

再看一下代码,看起来像requestFactory成员是通过调用afterPropertiesSet()来创建的。什么时候打电话是正确的?这整个方法甚至是正确的方法吗?

谁能告诉我什么是正确的方法来做到这一点?当然,有一些正确的方法可以让用户名显示在Tomcat日志中?

感谢

回答

2

如果你谈论的是Tomcat的访问日志阀,这是不行的,因为Tomcat是不知道的Spring Security,你的应用程序中运行完全的。

SecurityContextHolderAwareRequestFilter默认情况下处于启用状态,但其效果不适用于上方位于过滤器链中的部分调用堆栈。这应该从您上面发布的doFilter方法中明显看出。由requestFactory创建的包装请求仅在过滤器链中的该点之下可见。

最简单的选择是在Spring Security之后添加自己的过滤器(例如在web.xml),然后将想要的信息转储到日志中。或者,您可以使用它在MDC中为日志包设置用户名,例如log4jlogback,这将允许您将其添加到日志记录模式。以上链接中的UserServletFilter为例。