Spring自定义过滤器仅在指定的URL上执行一次

时间:2016-12-22 13:35:56

标签: spring jsf spring-security servlet-filters

我正在扩展WebSecurityConfigurerAdapter,覆盖configure方法。 我的目标是在绕过登录页面的特定URL上放置一个过滤器并进行手动身份验证。为此,我需要仅在用户第一次尝试访问SECTION_WITH_FILTER URL时才执行过滤器。 那是我的代码:

@Autowired
MyFilter myFilter;

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

    logger.debug("<CONFIGURE HTTPSECURITY/>");

    http
            .authorizeRequests()
            .antMatchers("/login*.*", "/error.*", "/resources/**", "/javax**/**").permitAll()
            .antMatchers("/SECTION_WITH_FILTER/**").permitAll()
            .antMatchers("/", "/*.jsf", "/**/*.jsf", "/*.faces", "/**/*.faces").hasAnyRole("ADMIN")
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/login.jsf")
            .permitAll()
            .and()
            .logout()
            .invalidateHttpSession(false)
            .logoutSuccessUrl("/")
            .deleteCookies("JSESSIONID")
            .permitAll()
            .and().csrf().disable();
    http
            .addFilterBefore(myFilter, BasicAuthenticationFilter.class);

}

我的问题是,在网站的任何形式的每次提交后,过滤器都会启动。

我已尝试使用FilterRegistrationBean,仅在用户转到特定网址时才设置过滤器:

 @Bean
public FilterRegistrationBean filterRegistration() {

    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(myFilter);
    registration.addUrlPatterns("/SECTION_WITH_FILTER/**");
    registration.setName("myFilter");
    registration.setEnabled(true);
    return registration;
}

但是使用此方法会抛出StackOverflowError异常。

org.apache.catalina.core.StandardWrapperValve invoke
GRAVE: Servlet.service() for servlet [dispatcherServlet] in context with    path [] threw exception [Filter execution threw an exception] with root cause
java.lang.StackOverflowError
    at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:231)
    at org.apache.catalina.core.ApplicationHttpRequest.getSession(ApplicationHttpRequest.java:589)
...

如何更改我的代码以针对仅在用户首次尝试访问时启动的单个网址指定过滤器? 感谢

1 个答案:

答案 0 :(得分:2)

您可以实施OncePerRequestFilter,覆盖doFilterInternal方法来开展自己的业务,如果某些网址不应过滤,则可以覆盖shouldNotFilter方法。

此过滤器用于标识已过滤请求。默认实现基于具体过滤器实例的已配置名称。