簡體   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