2015-12-16 32 views
8

Szukam nieinwazyjnego sposobu dodawania filtra captcha dla niektórych połączeń API.Howto dodatkowo dodać filtr captcha Spring Security dla konkretnych adresów URL tylko

Moja konfiguracja składa się z dwóch WebSecurityConfigurerAdapters z jednym filtrem każdy (nie filtru captcha):

  • api Wewnętrzne („/ IAPI” Zastosowanie filtrować na wszystkich połączeń, ale również ignorować niektóre publicznych żądań jak/Uwierzytelnij)
  • zewnętrznego interfejsu API ("/ EAPI" zastosowanie Filtr B na wszystkich połączeń)

Ho w Czy mogę dodać filtr przed rzeczy Spring Security, publicznych, wewnętrznych api lub zewnętrznych api? Nie potrzebuję SecurityContext, wystarczy sprawdzić Captcha w nagłówkach żądań, przesłać filtr Filterhhain (zwykłe filtry) lub ręcznie odmówić dostępu. Próbowałem zadeklarować filtr w web.xml, ale to łamie zdolność do korzystania z wtrysku zależności.

Tu jest mój konfiguracji zabezpieczeń Wiosna:

@EnableWebSecurity 
public class SpringSecurityConfig { 
    @Configuration 
    @Order(1) 
    @EnableGlobalMethodSecurity(securedEnabled = true) 
    public static class InternalApiConfigurerAdapter extends WebSecurityConfigurerAdapter { 

     @Autowired 
     private Filter filterA; 

     public InternalApiConfigurerAdapter() { 
      super(true); 
     } 

     @Override 
     public void configure(WebSecurity web) throws Exception { 
      web 
        .ignoring() 
        .antMatchers("/public/**"); 
     } 

     @Override 
     protected void configure(HttpSecurity http) throws Exception { 
      http 
        .antMatcher("/iapi/**") 
        .exceptionHandling().and() 
        .anonymous().and() 
        .servletApi().and() 
        .authorizeRequests() 
        .anyRequest().authenticated().and() 
        .addFilterBefore(filterA, (Class<? extends Filter>) UsernamePasswordAuthenticationFilter.class); 
     } 

     @Override 
     @Bean 
     public AuthenticationManager authenticationManagerBean() throws Exception { 
      return authenticationManager(); 
     } 
    } 

    @Configuration 
    @Order(2) 
    @EnableGlobalMethodSecurity(securedEnabled = true) 
    public static class ExternalApiConfigurerAdapter extends WebSecurityConfigurerAdapter { 

     @Autowired 
     private FilterB filterB; 

     public ExternalApiConfigurerAdapter() { 
      super(true); 
     } 

     @Override 
     protected void configure(HttpSecurity http) throws Exception { 
      http 
        .antMatcher("/external/**") 
        .exceptionHandling().and() 
        .anonymous().and() 
        .servletApi().and() 
        .authorizeRequests() 
        .anyRequest().authenticated().and() 
        .addFilterBefore(filterB, (Class<? extends Filter>) UsernamePasswordAuthenticationFilter.class); 
     } 

     @Override 
     @Bean 
     public AuthenticationManager authenticationManagerBean() throws Exception { 
      return authenticationManager(); 
     } 
    } 

Aktualizacja: W tej chwili mam konfigurację roboczą z filtrem zadeklarowanej w web.xml. Ma jednak tę wadę, że jest oddzielony od kontekstu wiosennego (np. Bez automatycznego tworzenia fasoli), więc szukam lepszego rozwiązania wykorzystującego sprężynę.

Podsumowanie: Istnieją dwa pozostałe problemy:

  1. dodać filtr dla konkretnych adresów URL tylko - używając beforeFilter (...) wewnątrz dowolnej konfiguracji Dodaje filtr do wszystkich adresów URL tej konfiguracji. Narzędzia antyspamowe nie działały. Potrzebuję czegoś takiego:/iapi/captcha/,/external/captcha/,/public/captcha/*.
  2. Mam publiczne api, które całkowicie pomija Spring Security: (web .ignoring() .antMatchers ("/ public/**");). Muszę ominąć Spring Security, ale nadal zadeklarować tam filtr, używając Spring autowiring, ale niekoniecznie Spring Security, ponieważ mój filtr captcha odrzuca lub przekierowuje połączenia w sposób bezpaństwowy.
+1

Mówisz o "Filtrze A" i "Filtrze B". Czy są one elementami zastępczymi dla twojego filtru captcha, czy też masz na to realną implementację? Jeśli tak, czy możesz odpowiednio zaktualizować swoje pytanie? –

+1

Nie jestem pewien, czy to dokładnie to, czego szukasz, ale znalazłeś [tę odpowiedź] (http://stackoverflow.com/a/11929129/4207875) na podobne pytanie. Różnice polegają na tym, że dodają filtr na końcu łańcucha, a konfiguracja jest w XML, ale w javaconfig, http.addFilterBefore() również działa. – saljuama

+0

@ksokol Są to filtry obecnego systemu, nie chcę ich dotykać. – Journeycorner

Odpowiedz

5

Masz już działającą konfigurację z filtrami A i B wstawionymi przed UsernamePasswordAuthenticationFilter, więc powinno być łatwo dodać inny niestandardowy filtr.

Po pierwsze, należy utworzyć filtr i zadeklarować ją jako fasoli, albo adnotacji klasę z @Component lub jako @Bean wewnątrz @Configuration klasy, więc jest gotowy do wstrzyknięcia @Autowired.

Teraz możesz wstrzyknąć go jako filtr A i B i go użyć.Według sekcji w dokumentacji referencyjnej Wiosna Bezpieczeństwa Filter Ordering, pierwszy filtr w łańcuchu jest ChannelProcessingFilter, tak aby wstawić filtr zanim cokolwiek innego w łańcuchu filtrów Wiosna Bezpieczeństwa, można to zrobić:

@Autowired 
private CaptchaFilter captchaFilter; 

@Override 
protected void configure(HttpSecurity http) throws Exception { 
    http 
      .antMatcher("/iapi/**") 
      .addFilterBefore(captchaFilter, (Class<? extends Filter>) ChannelProcessingFilter.class) 
      .addFilterBefore(filterA, (Class<? extends Filter>) UsernamePasswordAuthenticationFilter.class) 
      .authorizeRequests() 
       .anyRequest().authenticated(); 
    } 

Nawiasem mówiąc, exceptionHandling()anonymous() i servletApi() nie są potrzebne, ponieważ przy przedłużaniu WebSecurityConfigurerAdapter, to są już wliczone w cenę, z wyjątkiem anonymous() kiedy rzeczywiście podać więcej szczegółów konfiguracyjnych, jak stwierdza HttpSecurity javadoc

Pamiętaj, że sprężyna bezpieczeństwa "entrypoin t ", DelegatingFilterProxy nadal będzie wykonywane przed twoim filtrem, ale ten komponent deleguje tylko żądanie do pierwszego filtra w łańcuchu, który w tym przypadku byłby CaptchaFilter, więc naprawdę wykonasz filtr przed wszystkim innym z Spring Security .

Ale jeśli nadal chcesz, aby filtr captcha był wykonany przed DelegatingFilterProxy, nie można tego zrobić w konfiguracji Spring Security i musisz zadeklarować go w pliku web.xml.


Aktualizacja: Jeśli nie pragną zawierać filtr captcha w innych konfiguracjach, zawsze można dodać trzeci konfigurację, a klasa konfiguracje byłby następujący:

@EnableWebSecurity 
@EnableGlobalMethodSecurity(securedEnabled = true) 
public class SpringSecurityConfig { 

    @Configuration 
    @Order(1) 
    public static class CaptchaApiConfigurerAdatper extends WebSecurityConfigurerAdapter { 

     @Autowired 
     private CaptchaFilter captchaFilter; 

     public CaptchaApiConfigurerAdatper() { 
      super(true); 
     } 

     @Override 
     public void configure(WebSecurity web) throws Exception { 
      web 
        .ignoring() 
        .antMatchers("/public/**"); 
     } 

     @Override 
     protected void configure(HttpSecurity http) throws Exception { 
      http 
        .requestMatchers() 
         .antMatcher("/iapi/captcha**") 
         .antMatcher("/external/captcha**") 
         .and() 
        .addFilterBefore(captchaFilter, (Class<? extends Filter>) ChannelProcessingFilter.class) 
        .authorizeRequests() 
         .anyRequest().authenticated(); 
     } 
    }    

    @Configuration 
    @Order(2) 
    public static class InternalApiConfigurerAdapter extends WebSecurityConfigurerAdapter { 

     // ommiting code for the sake of clarity 
    } 

    @Configuration 
    @Order(3) 
    public static class ExternalApiConfigurerAdapter extends WebSecurityConfigurerAdapter { 

     // ommiting code for the sake of clarity 
    } 

przez sposób, kolejna wskazówka, możesz zreorganizować całą wspólną konfigurację poza konkretnymi konfiguracjami, do głównej klasy, na przykład @EnableGlobalMethodSecurity(securedEnabled = true), AuthenticationManager, WebSecurity, aby pominąć ochronę dla publiczności, ale dla tych, ponieważ główna klasa nie rozszerza niczego, co powinieneś @Autowire deklaracje metod.

Chociaż nie byłby jeden problem z WebSecurity, jeśli ignorują /public/** dopasowujący dla HttpSecurity z /public/captcha** będą ignorowane, więc myślę, czy nie powinni byłaby zewnątrz WebSecurity i mają inny wzorzec w klasie CaptchaConfig tak to się nie nakłada.

+0

Przepraszam, już próbowałem tego podejścia. Będzie używał tych dwóch filtrów na każde żądanie, ale potrzebuję konkretnych ścieżek. Również nadal nie wiem, jak dodać je na połączenia nie Spring Security. Odpowiednio zaktualizowałem moje pytanie. Dzięki za wskazówkę dotyczącą obsługi wyjątków, te rzeczy pomagają mi lepiej zrozumieć Spring Security! – Journeycorner

+0

Nic nie stoi na przeszkodzie, aby dodać trzecią konfigurację filtru captcha, wystarczy pamiętać o '@ Order', zaktualizuję odpowiedź na przykładzie. – saljuama