繁体   English   中英

Spring Boot 过滤器被调用两次或根本不调用

[英]Spring boot filter called twice or not called at all

我实现了一个 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());
        });
    }

}

我的 WebSecurityConfigurerAdapter 类:

@Configuration
public class AuthSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        //configuring strategy
        http.sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()
                .anyRequest().authenticated().and()
                .oauth2ResourceServer().jwt().and();
        http.csrf().disable();
        http.addFilterBefore(new MyCustomFilter (), UsernamePasswordAuthenticationFilter.class);
        http.exceptionHandling().authenticationEntryPoint(new AuthExceptionEntryPoint());
    }

}

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

Sending request to next chain for validation..
Sending request to next chain for validation..
Authentication completed sucessfully
Authentication completed sucessfully

我找到了一些关于问题的帖子,并尝试了以下解决方案:

  1. 发生这种情况是因为 spring 自动注册了 bean,而我在配置方法中手动添加了过滤器。 因此,我删除了在 configure() 方法中手动添加过滤器。 结果是根本没有调用过滤器。

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

  3. 还尝试删除@Component注释并手动添加过滤器。 此外,我必须将CookieProcessor bean 移至 Configuration 类。 之后出现的问题是应用程序无法启动,因为以下错误:

    引起:org.springframework.beans.BeanInstantiationException:无法实例化[org.springframework.web.servlet.HandlerMapping]:工厂方法'resourceHandlerMapping'抛出异常; 嵌套异常是 java.lang.IllegalStateException: No ServletContext set

我正在使用 spring-security 版本 5.3.3。

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

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

将以下@Bean方法添加到您的@SpringBootApplication注释类中

@Bean
public TomactContextCustomizer cookieProcessorCustomizer() {
  return (context) -> context.setCookieProcessor(new LegacyCookieProcessor());
}

现在在您的Filter中删除@Component添加一个伴随的FilterRegistrationBean以防止将其添加到常规过滤器链中。 (Spring Boot 自动将所有检测到的Filter实例注册到常规过滤器链)。

@Bean
public FilterRegistrationBean<MyFilter> myFilterRegistrationBean(MyFilter myFilter) {
  FilterRegistrationBean<MyFilter> frb = new FilterRegistrationBean<>(myFilter);
  frb.setEnabled(false);
  return frb;
}

如果您删除@Component ,则不需要上述代码段,如果您不这样做,则应在安全配置中重用扫描的MyFilter实例。

@Configuration
public class AuthSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyFilter myFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        //configuring strategy
        http.sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()
                .anyRequest().authenticated().and()
                .oauth2ResourceServer().jwt().and();
        http.csrf().disable();
        http.addFilterBefore(myFilter, UsernamePasswordAuthenticationFilter.class);
        http.exceptionHandling().authenticationEntryPoint(new AuthExceptionEntryPoint());
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM