为什么异步终端会调用两次过滤器链

时间:2017-06-21 15:16:14

标签: spring spring-boot spring-security

我正在开发一个基于Spring启动的应用程序。我注意到,对于异步端点,身份验证过滤器被调用两次,对于常规端点,它被调用一次。我找不到原因,但我在网https://jira.spring.io/browse/SPR-12608中发现了一个问题,其中说异步端点的过滤器在异步端点执行之前和之后被调用两次。它将解释双重身份验证调用。我想知道这是预期的行为,为什么这样做以及如何避免双重身份验证。

UPD: 我找到了一种方法,以避免在异步端点完成后第二次触发过滤器。我需要做的是分析为请求分配了哪种调度程序,如果它是异步的 - 继续进行过滤器链。我在筛选器中添加了以下方法:

@Override
public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {
    if (request.getDispatcherType() == DispatcherType.ASYNC) {
        filterChain.doFilter(request, response);
    } else {
        super.doFilter(request, response, filterChain);
    }
}

2 个答案:

答案 0 :(得分:1)

我看到完全相同的行为,我认为这与异步调用分为两个阶段的事实有关。

首先,启动常规容器线程并生成临时响应,但是在异步调度程序竞争之前,该响应不会被返回给客户端。完成异步线程后,处理临时响应将替换为异步线程中的实际响应并返回给客户端。

两个线程都经过相同的过滤器链。因此,您会看到重复调用。

如果您希望在扩展OncePerRequestFilter后调用过滤器。它将检查您的过滤器是否已在请求过程中被调用(即使请求处理包含两个阶段,每个阶段由他们自己的线程处理)。

答案 1 :(得分:1)

我对类AbstractAuthenticationProcessingFilter的具体实现存在相同的问题,我很想解决它。最好为实现OncePerRequestFilter的whaterver类创建一个自定义实现,在我的特殊情况下,我创建了一个AuthenticationFilter的实现。