2016-01-30 6 views
1

Когда в метод настройки HttpSecurity добавлено несколько фильтров, они кажутся перекрывающимися, поскольку в то время работает только один.Защитные фильтры перекрываются

Это метод настройки:

Я пытался указать порядок, но проблема по-прежнему сохраняется:

@Bean 
public FilterRegistrationBean securityFilterChain(@Qualifier(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) Filter securityFilter) { 
    FilterRegistrationBean registration = new FilterRegistrationBean(securityFilter); 
    registration.setOrder(Integer.MAX_VALUE - 2); 
    registration.setName(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME); 
    return registration; 
} 

@Bean 
public FilterRegistrationBean ssoFilterRegistrationBean() throws Exception { 
    FilterRegistrationBean registrationBean = new FilterRegistrationBean(); 
    registrationBean.setFilter(ssoFilter()); 
    registrationBean.setOrder(Integer.MAX_VALUE-1); 
    return registrationBean; 
} 

@Bean 
public FilterRegistrationBean csrfFilterRegistrationBean() throws Exception { 
    FilterRegistrationBean registrationBean = new FilterRegistrationBean(); 
    registrationBean.setFilter(csrfHeaderFilter()); 
    registrationBean.setOrder(Integer.MAX_VALUE); 
    return registrationBean; 
} 

Я следовал следующей нити без успеха.

Filter order in spring-boot

https://github.com/spring-projects/spring-boot/issues/1640

https://github.com/spring-projects/spring-boot/issues/677

Любая помощь будет оценен по достоинству!

UPDATE:

определение CSRF Фильтр

private Filter csrfHeaderFilter() { 
    return new OncePerRequestFilter() { 
     @Override 
     protected void doFilterInternal(HttpServletRequest request, 
             HttpServletResponse response, FilterChain filterChain) 
       throws ServletException, IOException { 
      CsrfToken csrf = (CsrfToken) request 
        .getAttribute(CsrfToken.class.getName()); 
      if (csrf != null) { 
       Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN"); 
       String token = csrf.getToken(); 
       if (cookie == null 
         || token != null && !token.equals(cookie.getValue())) { 
        cookie = new Cookie("XSRF-TOKEN", token); 
        cookie.setPath("/"); 
        response.addCookie(cookie); 
       } 
      } 
      filterChain.doFilter(request, response); 
     } 
    }; 
} 

SSO определение фильтра:

public class SSORequestHeaderAuthenticationFilter extends RequestHeaderAuthenticationFilter { 

private boolean allowPreAuthenticatedPrincipals = true; 

public SSORequestHeaderAuthenticationFilter() { 
    super(); 
    //TODO Pull this value from a properties file (application.properties, or localstrings.properties) 
    //NOTE SM_USER is the default, but you can change it like this (your company may use some other header) 
    //this.setPrincipalRequestHeader("SM_USER"); 
} 


@Override 
public void doFilter(ServletRequest request, ServletResponse response, 
        FilterChain chain) throws IOException, ServletException { 
    chain.doFilter(request, response); 
} 

/** 
* This is called when a request is made, the returned object identifies the 
* user and will either be {@literal null} or a String. This method will throw an exception if 
* exceptionIfHeaderMissing is set to true (default) and the required header is missing. 
* 
* @param request {@link javax.servlet.http.HttpServletRequest} 
*/ 
@Override 
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) { 
    String userName = (String) (super.getPreAuthenticatedPrincipal(request)); 
    if (userName == null || userName.trim().equals("")) { 
     return userName; 
    } 

    return userName; 
} 

public boolean isAllowPreAuthenticatedPrincipals() { 
    return allowPreAuthenticatedPrincipals; 
} 
} 
+0

Можете ли вы добавить код фильтра? – Cyril

+0

Только вопрос. Используете ли вы OAuth2 и @ EnableOauth2Sso и пытаетесь выполнить аутентификацию запросов, содержащих токен-носитель, в заголовке авторизации? Я сделал это несколько дней назад. Если это то, чего вы хотите достичь, я мог бы предоставить вам решение –

+0

@YannicKlem oh god yes !!!! Это точно мое дело, это приложение имеет аннотацию @ EnableOaut2Sso, и он сохраняет токен для отправки в другое приложение в качестве перенаправления, поэтому у меня есть фильтр csrf :) спасибо, что это действительно помогло бы! –

ответ

0

Я предполагаю, что вы не всегда выполняет FilterChain.doFilter метод внутри обоих фильтров. Затем цепь фильтра останавливается и выполняется только один из ваших пользовательских фильтров. В этом простом примере оба фильтра выполнены:

@Configuration 
@EnableWebSecurity 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
       .addFilterBefore(new Filter1(), RequestHeaderAuthenticationFilter.class) 
       .addFilterAfter(new Filter2(), CsrfFilter.class) 
       .authorizeRequests() 
       .anyRequest().authenticated() 
       .and() 
       .httpBasic() 
       .and() 
       .logout() 
       .permitAll(); 
    } 

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

    static class Filter1 extends OncePerRequestFilter { 
     @Override 
     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 
      System.out.println("executed filter 1"); 
      filterChain.doFilter(request, response); 
     } 
    } 

    static class Filter2 extends OncePerRequestFilter { 
     @Override 
     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 
      System.out.println("executed filter 2"); 
      filterChain.doFilter(request, response); 
     } 
    } 

} 
+0

Пробовал, не работал :(. Я уточню вопрос с помощью определения фильтра. –

0

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

Я предлагаю вам прекратить беспокоиться о заказе в вашем FilterRegistrationBeans и использовать их, чтобы отключить регистрацию контейнера (установив их флаг включения в значение false). Затем подумайте о порядке ваших цепей фильтров, как указано @Order на вашем WebSecurityConfigurers. И, наконец, вы можете решить, имеет ли порядок фильтров в заданной цепочке, и если он использует методы addFilter{Before,After}.

+0

Прежде чем дать ему попробовать с FilterRegistrationBean, я использовал addFilterBefore и addFilterAfter, но даже когда работал только с ssoFilter, csrf был даже не вызывать. –

+0

Прочтите ответ еще раз. Если ваши пользовательские фильтры объявлены как bean-компоненты, вам необходимо отключить регистрацию контейнера. Фильтр, не срабатывающий, не означает, что он не зарегистрирован. –

+0

Я сделал, как вы сказали, и получил csrf работа фильтров. Вещь, и я оглядываюсь, если кто-то испытал это раньше, preAuthProvider *, для которого я использую ssoFilter() для), полностью изменить основной объект, и, следовательно, потерять значения, которые имеют отношение к csrfFilter, который теперь стал проблема. Есть ли способ изменить список полномочий в объекте Principal во время процесса аутентификации приложения? –

0

Фильтр, который делает то, что вы хотите сделать, уже существует. Его OAuth2AuthenticationProcessingFilter. Этот фильтр используется, если вы аннотируете приложение с помощью @EnableResourceServer. Если вы это сделаете, это приведет к тому, что теперь будет работать только аутентификация на основе токенов. Чтобы установить другие способы аутентификации, установите флаг состояния без фильтра false.

Что я сделал, так это создать класс ApiTokenAccessFilter, который расширяет OAuth2AuthenticationProcessingFilter. Этот фильтр принимает параметр конструктора ResourceServerTokenServices и устанавливает флаг состояния без значения false.

public class ApiTokenAccessFilter extends OAuth2AuthenticationProcessingFilter { 

    public ApiTokenAccessFilter(ResourceServerTokenServices resourceServerTokenServices) { 

    super(); 
    setStateless(false); 
    setAuthenticationManager(oauthAuthenticationManager(resourceServerTokenServices)); 
    } 

    private AuthenticationManager oauthAuthenticationManager(ResourceServerTokenServices tokenServices) { 

    OAuth2AuthenticationManager oauthAuthenticationManager = new OAuth2AuthenticationManager(); 

    oauthAuthenticationManager.setResourceId("oauth2-resource"); 
    oauthAuthenticationManager.setTokenServices(tokenServices); 
    oauthAuthenticationManager.setClientDetailsService(null); 

    return oauthAuthenticationManager; 
    } 
} 

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

@Configuration 
@EnableOAuth2Sso 
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private ResourceServerTokenServices tokenServices; 

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

    http.authorizeRequests() 
     .anyRequest() 
     .authenticated() 
     .and() 
     .addFilterBefore(new ApiTokenAccessFilter(tokenServices), AbstractPreAuthenticatedProcessingFilter.class); 
    } 
} 

Я думаю, что это может быть проще, так что я открыл вопрос о spring-security-oauth Github repo. Я не уверен, что это решение, но я не нашел другой альтернативы.

Смежные вопросы