我们正在使用Spring Security来保护我们的Spring Web应用程序。实际上我们正在使用Spring Social身份验证过滤器。让它运作并不容易,但它现在有效,一切都很棒。
唯一缺少的是用户名未出现在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);
}
chain参数为null(不太可能)或requestFactory成员为null。
再看一下代码,看起来像requestFactory成员是通过调用afterPropertiesSet()创建的。什么时候才能打电话?这整个方法是否是正确的方法?
谁能告诉我这是怎样的正确方法?当然有一些正确的方法可以让用户名显示在Tomcat日志中吗?
由于
答案 0 :(得分:2)
如果您正在谈论Tomcat的访问日志阀,这将无效,因为Tomcat不知道Spring Security,它完全在您的应用程序中运行。
SecurityContextHolderAwareRequestFilter
通常默认启用,但其效果不适用于调用堆栈中位于过滤器链中的部分。从上面发布的doFilter
方法中可以看出这一点。由requestFactory
创建的包装请求仅在过滤器链中的该点下方可见。
最简单的选择是在Spring Security之后添加您自己的过滤器(例如在web.xml
中),并将您想要的信息转储到日志中。或者,您可以使用它在MDC
中为log4j
或logback
等日志记录包设置用户名,这样您就可以将其添加到日志记录模式中。有关示例,请参阅上面链接中的UserServletFilter
。