2016-05-18 10 views
2

私は、スプリングブートとスプリングJavaの設定を使用して、カスタム認証フィルタを使用して2つの異なるhttp Web構成を使用したいと考えています。 サンプルアプリケーションは、https://github.com/spring-projects/spring-security-javaconfig/blob/master/samples-web.md#sample-multi-http-web-configurationにあります。 これは、それぞれのウェブ構成に対して個別のスプリング・フィルター・チェーンで終わると私は理解していました。しかし、両方のフィルタが呼び出されますが、Web設定のurlパターンは要求と一致しません。 たとえば、http://localhost:8080/api/dosomethingを要求すると、CustomApiAuthenticationFilterだけでなく、両方のフィルタが呼び出されます。もちろん、doFilterInternalでリクエストURLを確認し、一致しない場合はリクエストを無視することは可能ですが、これは対応するWeb設定のurlパターンを尊重して自動的に行うべきだと考えました。 さらに、私のRestControllerはそれぞれ呼び出されることはありません。Postmanはレスポンスボディがない状態コード200 OKしか受け取りません。Java Configを使用した複数のHttpSecurityオブジェクトのカスタム認証フィルタ

2つの質問: 1.これは仕様によるものですか、構成が間違っていますか? 2. RestControllerが呼び出されないのはなぜですか?

@EnableWebSecurity 
public class SecurityConfiguration { 

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

     @Bean 
     public GenericFilterBean apiAuthenticationFilter() { 
      return new CustomApiAuthenticationFilter(); 
     } 

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

      http.antMatcher("/api/**").addFilterAfter(apiAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class) 
       .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
       .and() 
       .authorizeRequests().antMatchers("/api/**").authenticated(); 
     } 
    } 

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

     @Bean 
     public GenericFilterBean webAuthenticationFilter() { 
      return new CustomWebAuthenticationFilter(); 
     } 

     @Override 
     protected void configure(HttpSecurity http) throws Exception { 
      http.antMatcher("/").addFilterAfter(webAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class) 
       .authorizeRequests().antMatchers("/").authenticated(); 
     } 
    } 
} 

public class CustomApiAuthenticationFilter extends OncePerRequestFilter { 
    @Override 
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 
     Authentication auth = new UsernamePasswordAuthenticationToken("sub", "password", ImmutableList.of(new SimpleGrantedAuthority("API"))); 
     SecurityContextHolder.getContext().setAuthentication(auth); 
    } 
} 

public class CustomWebAuthenticationFilter extends OncePerRequestFilter { 
    @Override 
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 
     Authentication auth = new UsernamePasswordAuthenticationToken("sub", "password", ImmutableList.of(new SimpleGrantedAuthority("USER"))); 
     SecurityContextHolder.getContext().setAuthentication(auth); 
    } 
} 

@RestController 
public class ApiController { 
    @RequestMapping(value = "/api/v1/dosomething", method = RequestMethod.GET) 
    public String getSomething() { 
     return "something"; 
    } 
} 
+0

フィルタはBeanです。 Springブートはそれらを検出し、Spring Securityフィルタチェーンだけでなく、通常のフィルタチェーンに追加します。したがって、おそらく1度ではなく2度呼び出されることさえあります。 –

+0

'OncePerRequestFilter'を拡張すると、それらは一度だけ呼び出されますが、問題はフィルタが通常の' javax.servlet.Filter'として検出され、通常のフィルタとして追加されるという点です。したがって、実行は –

+0

です。さて、 '@ Bean'アノテーションを削除した後、正しいフィルタだけが呼び出されます。しかし、私はまだ私の 'RestController'が呼び出されないという問題があります。何か案は? – oliver

答えて

0

、手動で対応するスプリングFilterRegistrationBeanを作成し、フィルタ自動登録を無効にすることによって@Bean注釈を維持することも可能です。これにより、フィルタでのオートワイヤリングも保持されます。

public class SecurityConfiguration { 

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

     @Bean 
     public FilterRegistrationBean customApiAuthenticationFilterRegistration() { 
      FilterRegistrationBean registration = new FilterRegistrationBean(customApiAuthenticationFilter()); 
      registration.setEnabled(false); 
      return registration; 
     } 

     @Bean 
     public GenericFilterBean customApiAuthenticationFilter() { 
      return new CustomApiAuthenticationFilter(); 
     } 

     @Override 
     protected void configure(HttpSecurity http) throws Exception { 
      http.antMatcher("/api/**").addFilterAfter(customApiAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class) 
       .authorizeRequests().anyRequest().hasRole("API").and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); 

     } 
    } 

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

     @Bean 
     public FilterRegistrationBean customWebAuthenticationFilterRegistration() { 
      FilterRegistrationBean registration = new FilterRegistrationBean(customWebAuthenticationFilter()); 
      registration.setEnabled(false); 
      return registration; 
     } 

     @Bean 
     public GenericFilterBean customWebAuthenticationFilter() { 
      return new CustomWebAuthenticationFilter(); 
     } 

     @Override 
     protected void configure(HttpSecurity http) throws Exception { 
      http.antMatcher("/").addFilterAfter(customWebAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class) 
       .authorizeRequests().antMatchers("/").hasRole("USER"); 
     } 
    } 
} 
0

正解をくれたM. Deinumに感謝します。次のようになりましたが、これが正当なアプローチであるかどうかはまだ分かりません。私の前の回答に加えて

@EnableWebSecurity 
public class SecurityConfiguration { 

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

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

      http.antMatcher("/api/**") 
       .addFilterAfter(new CustomApiAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class) 
       .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
       .and() 
       .authorizeRequests().anyRequest().hasRole("API"); 
     } 
    } 

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

     @Override 
     protected void configure(HttpSecurity http) throws Exception { 
      http.antMatcher("/") 
       .addFilterAfter(new CustomWebAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class) 
       .authorizeRequests().anyRequest().hasRole("USER"); 
     } 
    } 
} 

public class CustomApiAuthenticationFilter extends OncePerRequestFilter { 
    @Override 
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 
     Authentication auth = new UsernamePasswordAuthenticationToken("sub", "password", ImmutableList.of(new SimpleGrantedAuthority("ROLE_API"))); 
     SecurityContextHolder.getContext().setAuthentication(auth); 
     filterChain.doFilter(request, response); 
    } 
} 

public class CustomWebAuthenticationFilter extends OncePerRequestFilter { 
    @Override 
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 
     Authentication auth = new UsernamePasswordAuthenticationToken("sub", "password", ImmutableList.of(new SimpleGrantedAuthority("ROLE_USER"))); 
     SecurityContextHolder.getContext().setAuthentication(auth); 
     filterChain.doFilter(request, response); 
    } 
}