Добавление настраиваемого фильтра, который будет вызываться после фильтра Spring-Security в среде Servlet 3+

Я использую Spring-Security 3.2.4 и Spring Boot 1.1.0 (и связанные с ним версии 4.X). Я пишу веб-приложение, которое будет работать во встроенном коте.

Я пытаюсь добавить два дополнительных фильтра (не связанных с безопасностью Spring), один из которых будет вызван до Spring-Security-FilterChainProxy, а другой будет вызван после Spring-Security-FilterChainProxy.

Мои файлы конфигурации Spring-Security:

@Configuration
@EnableWebMvcSecurity
public class SecurityCtxConfig extends WebSecurityConfigurerAdapter {

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth
    .inMemoryAuthentication()
        .withUser("user").password("pass").roles("USER");
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf()
            .disable()
            .authorizeRequests()
            .anyRequest()
            .authenticated()
            .and()
            .formLogin()
            .usernameParameter("user").passwordParameter("password");
}
}

И Основной класс (Application.class):

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {

    @Bean
RequestFilter beforeSpringSecurityFilter(){
    return new RequestFilter();
}

@Bean
RequestFilter afterSpringSecurityFilter(){
    return new RequestFilter();
}

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

И реализация фильтра:

public class RequestFilter extends OncePerRequestFilter {

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
        FilterChain filterChain) throws ServletException, IOException {
        filterChain.doFilter(request, response);
}

}

Есть ли способ управления порядком вызова, если принять во внимание FilterChainProxy (который создается WebSecurityConfigurerAdapter? Чтобы быть точным, требуется следующий порядок:

  1. запрос-фильтр-1
  2. Spring-Security FilterChain
  3. запрос-фильтр-2

Спасибо

4 ответа

Решение

FilterChainProxy использование Spring Security не Ordered (если бы вы могли заказать все ваши фильтры). Но вы должны быть в состоянии зарегистрировать его в FilterRegistrationBean который является Ordered и зарегистрируйте ваши другие фильтры таким же образом. В случае фильтра безопасности вы можете ввести его по имени в компонент регистрации. Другие вы, вероятно, можете ввести, позвонив @Bean метод.

Согласен со всем, что было сказано Дейвом Сайером;), но хотел бы добавить пример конфигурации Java с использованием FilterRegistrationBean.

В моей ситуации я обнаружил, что мой пользовательский фильтр безопасности (использующий Spring Security) запускался дважды для каждого запроса. Добавление FilterRegistrationBean конфиг исправил это.

    @Bean(name = "myFilter")
    public MyAuthenticationFilter myAuthenticationFilter(final MyAuthenticationEntryPoint entryPoint) {
        final MyAuthenticationFilter filter = new MyAuthenticationFilter();
        filter.setEntryPoint(entryPoint);
        return filter;
    }

    /**
     *  We do this to ensure our Filter is only loaded once into Application Context
     *
     */
    @Bean(name = "authenticationFilterRegistration")
    public FilterRegistrationBean myAuthenticationFilterRegistration(final MyAuthenticationFilter filter) {
        final FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(filter);
        filterRegistrationBean.setEnabled(false);
        return filterRegistrationBean;
    }

(Относительно моей конкретной проблемы с фильтром, который был зарегистрирован дважды в контексте приложения - вместо того, чтобы использовать FilterRegistrationBeanЯ также нашел повторную реализацию MyAuthenticationFilter наследовать от OncePerRequestFilter вместо GenericFilterBean тоже сработало. Тем не мение, OncePerRequestFilter поддержка от Servlet 3.x и выше, и поскольку я писал публичную библиотеку, поддержка Servlet 2.x может понадобиться)

В какой-то момент весенняя загрузка показала фильтр безопасности как свойство. Сейчас это сделать довольно легко.

В вашем приложении.yml:

        spring:
    security:
      filter:
        order: 20

И какой-то фильтр, который вы хотите вызвать после того, как Spring Security сделает это:

      @Bean
public FilterRegistrationBean<Filter> afterAuthFilterRegistrationBean() {
    FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>();
    //a filter that extends OncePerRequestFilter
    AfterAuthFilter afterAuthFilter = new AfterAuthFilter();
    registrationBean.setFilter(afterAuthFilter);
    //this needs to be a number greater than than spring.security.filter.order
    registrationBean.setOrder(30);
    return registrationBean;
}

Для фильтра, который выполняется перед безопасностью Spring, установите порядок на число меньше 20.

Если вы используете подходы web.xml, вы можете выполнить следующие действия: /questions/25904704/kak-napisat-sobstvennyij-filtr-v-spring-security/25904716#25904716

Если вы используете подходы конфигурации Java, вы можете сделать это в WebSecurityConfigurerAdapter

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

    http.addFilterBefore(your-request-filter-1, ChannelProcessingFilter.class);
    http.addFilterAfter(your-request-filter-2, SwitchUserFilter.class);

}

Всегда проверяйте версию библиотеки, которую вы используете, и обращайтесь к конкретному документу для правильного порядка цепочек фильтров:

https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/

Или, если вы используете AbstractSecurityWebApplicationInitializer, вы можете использовать insertFilters или же appendFilters,

public class SecurityApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

    @Override
    protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
        insertFilters(servletContext, new MultipartFilter());
    }
}

Более подробная информация.

Другие вопросы по тегам