【问题标题】:Spring FilterChain + Security: log request with user or notSpring FilterChain + Security:是否使用用户记录请求
【发布时间】:2019-05-21 03:10:47
【问题描述】:

我有一个带有多个初始化程序的 Spring web-mvc REST 服务。

WebAppInitializer.java

@Order(1)
public class MyFiltersInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) {
        FilterRegistration.Dynamic registration = servletContext.addFilter("myRequestFilter", DelegatingFilterProxy.class);
        // register other filters and DispatcherServlet
    }
}

SecurityWebAppInitializer.java

@Order(2)
public class MySecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

    @Override
    protected Set<SessionTrackingMode> getSessionTrackingModes() {
        return EnumSet.of(SessionTrackingMode.COOKIE, SessionTrackingMode.URL);
    }
}

如您所见,SecurityFilterChain 被添加到所有自定义请求过滤器之后。我需要做的是记录每个请求,并在请求被授权时包含User 进行记录

类似MyRequestFilter.java:

@Slf4j
public class RequestFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(final HttpServletRequest request,
                                    final HttpServletResponse response,
                                    final FilterChain filterChain) throws ServletException, IOException {
           MyUser user = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); //no auth yet
           log.debug("request {} start, user {}", request, user); 
           filterChain.doFilter(request, response); //may return 401 or 403, what also need to be logged
           log.debug("request {} end with response {}", request, response);
   }

有个想法是加一个LogBodyHolder,保持log body直到SecurityChain完全通过,然后调用log.debug。但是有什么漂亮的方法可以解决这个问题吗?

【问题讨论】:

  • 你说的漂亮是什么意思?
  • 它使用了哪个日志框架?在 log4j 中有一个日志上下文,可用于存储需要包含在每行日志中的信息。检查Improved Java Logging with Mapped Diagnostic Context (MDC)。虽然这可能是题外话,因为我不确定我是否完全理解了这个问题

标签: java spring spring-mvc spring-security


【解决方案1】:

您可以创建一个扩展 Spring 提供的类 AbstractRequestLoggingFilter 的 Spring Bean,然后覆盖 beforeRequest()afterRequest() 方法以根据需要添加日志。

【讨论】:

  • 感谢您的提示,但这不是我正在寻找的逻辑。我需要的是每个请求的 single 日志,其中包含它在请求期间能够收集的所有信息。我的应用程序有一个过滤器,它可以清除 SecurityContext 事件,尽管它之前已初始化。目前的解决方案是创建一个队列来存储请求信息,直到请求完成并且FilterChain 完全完成。这似乎是解决这个问题的明显方法,但也许有标准的工具或模式。
猜你喜欢
  • 2020-08-29
  • 2015-08-25
  • 2015-12-03
  • 1970-01-01
  • 1970-01-01
  • 2012-06-15
  • 2010-12-17
  • 2016-07-19
  • 1970-01-01
相关资源
最近更新 更多