Java Spring引导筛选器已调用两次或根本未调用

Java Spring引导筛选器已调用两次或根本未调用,java,spring,spring-boot,spring-security,Java,Spring,Spring Boot,Spring Security,我实现了一个customFilter,它将请求Cookie中的内容添加到其标题中: @Component @Slf4j public class MyCustomFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {

我实现了一个customFilter,它将请求Cookie中的内容添加到其标题中:

@Component
@Slf4j
public class MyCustomFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
        .... some logic...
        log.info("Sending request to next chain for validation..");
        chain.doFilter(request, response);
        log.info("Authentication completed sucessfully");
    }

    @Bean
    // This method is needed to replace the default cookieFilter.json processor of tomcat that ignores the jwt cookieFilter.json
    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> cookieProcessorCustomizer() {
        return tomcatServletWebServerFactory -> tomcatServletWebServerFactory.addContextCustomizers((TomcatContextCustomizer) context -> {
            context.setCookieProcessor(new LegacyCookieProcessor());
        });
    }

}
当我运行代码并通过postman/curl发送请求时,我看到过滤器在

Sending request to next chain for validation..
Sending request to next chain for validation..
Authentication completed sucessfully
Authentication completed sucessfully
我找到了一些关于这个问题的帖子,并尝试了以下解决方案:

  • 这是因为spring自动注册bean,我在configure方法中手动添加了过滤器。因此,我删除了configure()方法中手动添加的过滤器。结果是根本没有调用过滤器

  • 尝试扩展
    OncePerRequestFilter
    类,而不是实现过滤器接口。这样做了,但过滤器仍然触发了两次

  • 还尝试删除
    @组件
    批注并手动添加筛选器。此外,我必须将
    CookieProcessor
    bean移动到配置类。之后出现的问题是,由于以下错误,应用程序无法启动:

    原因:org.springframework.beans.beans实例化异常:未能实例化[org.springframework.web.servlet.HandlerMapping]:工厂方法“resourceHandlerMapping”引发异常;嵌套异常为java.lang.IllegalStateException:未设置ServletContext


  • 我使用的是spring安全版本5.3.3。

    根据经验,不要将
    @Bean
    方法添加到
    @Component
    类中,因为这些方法的处理方式与
    @Configuration
    类中的不同。(见附件)

    @Bean
    中的代码太复杂。创建并返回一个
    TomcatContextCustomizer
    来进行修改。您的代码将导致循环引用,这将导致初始化错误

    将以下
    @Bean
    方法添加到
    @springbootplication
    注释类

    @Bean
    公共TomactContextCustomizer cookieProcessorCustomizer(){
    return(context)->context.setCookieProcessor(新的LegacyCookieProcessor());
    }
    
    现在,在您的
    过滤器中
    删除
    @组件
    或添加一个Accomping
    过滤器注册bean
    ,以防止它被添加到常规过滤器链中。(Spring Boot自动将所有检测到的
    过滤器
    实例注册到常规过滤器链)

    @Bean
    公共过滤器注册Bean myFilterRegistrationBean(MyFilter MyFilter){
    FilterRegistrationBean frb=新的FilterRegistrationBean(myFilter);
    frb.setEnabled(假);
    返回frb;
    }
    
    如果删除
    @组件
    ,则不需要上述代码段,如果不删除,则应在安全配置中重新使用扫描的
    MyFilter
    实例

    @配置
    公共类AuthSecurityConfig扩展了WebSecurity配置适配器{
    @自动连线
    私人MyFilter MyFilter;
    @凌驾
    受保护的无效配置(HttpSecurity http)引发异常{
    //配置策略
    http.sessionManagement()
    .sessionCreationPolicy(sessionCreationPolicy.STATELESS)和()
    .授权请求()
    .anyRequest().authenticated()和()
    .oauth2ResourceServer().jwt()和();
    http.csrf().disable();
    addFilterBefore(myFilter,UsernamePasswordAuthenticationFilter.class);
    http.exceptionHandling().authenticationEntryPoint(新的AuthExceptionEntryPoint());
    }
    }
    
    移除
    @组件
    。它目前是普通筛选链和安全筛选链的一部分,因此执行两次(也注册两次)。
    @Bean
    方法应位于
    @Configuration
    类上,而不是此
    @组件上。我将Bean移动到配置中,并得到以下错误:原因:org.springframework.beans.beanstantiationexception:未能实例化[org.springframework.web.servlet.HandlerMapping]:工厂方法“resourceHandlerMapping”引发异常;嵌套异常为java.lang.IllegalStateException:No ServletContext集合返回一个
    TomcatContextCustomizer
    ,并且不添加它。你把事情弄得太复杂了。我使用了以下代码,但仍然得到相同的错误:public TomcatContextCustomizer CookieProcessor Customizer(){return context->context.setCookieProcessor(new LegacyCookieProcessor());}首先,感谢你的清晰解释。我删除了@Component注释,因此我没有传递注入的bean,而是创建了一个过滤器的新实例,并在(..)之前传递给addFilterBefore。我试图运行它,但得到了相同的错误:(您还需要
    TomcatContextCustomizer
    否则将不会注册
    LegacyCookieProcessor
    。我没有编写它,但我将TomcatContextCustomizer Bean添加到我的@ConfigurationOn类中。当我在没有TomcatContextCustomizer方法的情况下运行代码时,spring应用程序启动,但我的Cookie被忽略stomizer,由于我前面提到的上下文错误,spring应用程序无法启动。解决方案将TomcatContextCustomizer移动到另一个@Configuration类,而不是将其保留在扩展WebSecurityConfigureAdapter的类中。感谢所有帮助!!