web-dev-qa-db-ja.com

Java構成とSpringSecurity3.2を使用したセキュリティメソッドアノテーション

_@EnableGlobalMethodSecurity_によって制御されるメソッドレベルのアノテーションを使用してアプリケーションをセットアップする際に問題が発生します。サーブレット3.0スタイルの初期化を使用しています。

_public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

    public SecurityWebApplicationInitializer() {
        super(MultiSecurityConfig.class);
    }
}
_

AuthenticationManagerを初期化する2つの異なる方法を、両方とも独自の問題で試みました。 not _@EnableGlobalMethodSecurity_を使用すると、サーバーが正常に起動し、すべてのフォームセキュリティが期待どおりに実行されることに注意してください。コントローラに_@EnableGlobalMethodSecurity_および@PreAuthorize("hasRole('ROLE_USER')")アノテーションを追加すると、問題が発生します。

フォームベースとAPIベースのセキュリティを個別に設定しようとしています。メソッドベースのアノテーションは、APIセキュリティでのみ機能する必要があります。

1つの構成は次のとおりです。

_@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class MultiSecurityConfig {

    @Configuration
    @Order(1)
    public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
        protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/api/**").httpBasic();
        }

        protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication()
                .withUser("user").password("password").roles("USER").and()
                .withUser("admin").password("password").roles("USER", "ADMIN");
        }
    }

    @Configuration
    public static class FormWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/static/**","/status");
        }

        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests().anyRequest().hasRole("USER").and()
                .formLogin().loginPage("/login").permitAll();
        }

        protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication()
                .withUser("user").password("password").roles("USER").and()
                .withUser("admin").password("password").roles("USER", "ADMIN");
        }
    }

}
_

認証メカニズムの登録は1つだけにしたいので、これは理想的ではありませんが、主な問題は、次の例外が発生することです。

_Java.lang.IllegalArgumentException: Expecting to only find a single bean for type interface org.springframework.security.authentication.AuthenticationManager, but found []
_

私の知る限り、_@EnableGlobalMethodSecurity_は独自のAuthenticationManagerを設定しているので、ここで何が問題なのかわかりません。

2番目の構成は次のとおりです。

_@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class MultiSecurityConfig {

    @Bean
    protected AuthenticationManager authenticationManager() throws Exception {
        return new AuthenticationManagerBuilder(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR)
                .inMemoryAuthentication()
                    .withUser("user").password("password").roles("USER").and()
                    .withUser("admin").password("password").roles("USER", "ADMIN").and()
                    .and()
                .build();
    }

    @Configuration
    @Order(1)
    public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
        @Override protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/api/**").httpBasic();
        }
    }

    @Configuration
    public static class FormWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/static/**","/status");
        }

        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests().anyRequest().hasRole("USER").and()
                .formLogin().loginPage("/login").permitAll();
        }
    }

}
_

この構成は実際には正常に開始されますが、例外があります

_Java.lang.IllegalArgumentException: A parent AuthenticationManager or a list of AuthenticationProviders is required
at org.springframework.security.authentication.ProviderManager.checkState(ProviderManager.Java:117)
at org.springframework.security.authentication.ProviderManager.<init>(ProviderManager.Java:106)
at org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder.performBuild(AuthenticationManagerBuilder.Java:221)
_

テストしたところ、セキュリティが機能していないことがわかりました。

私はこれを数日間見てきましたが、春のセキュリティ実装コードに飛び込んだ後でも、構成のどこが悪いのかわからないようです。

私はspring-security-3.2.0.RC1とspring-framework-3.2.3.RELEASEを使用しています。

12
Luke

WebSecurityConfigurerAdapterprotected registerAuthenticationメソッドを使用すると、認証がそのWebSecurityConfigurerAdapterにスコープされるため、EnableGlobalMethodSecurityはそれを見つけることができません。あなたがこれについて考えるならば...メソッドが保護されているのでそれは理にかなっています。

表示されているエラーは、実際にはデバッグステートメントです(レベルがDEBUGであることに注意してください)。その理由は、SpringSecurityがグローバルメソッドセキュリティを自動的に配線するためにいくつかの異なる方法を試みるためです。具体的には、EnableGlobalMethodSecurityは次の方法でAuthenticationManagerを取得しようとします。

  • GlobalMethodSecurityConfigurationを拡張してregisterAuthenticationをオーバーライドすると、渡されたAuthenticationManagerBuilderが使用されます。これにより、AuthenticationManagerを同じ方法で分離できます。 WebSecurityConfigurerAdapterでそうします
  • AuthenticationManagerBuilderのグローバル共有インスタンスからビルドしてみてください。失敗した場合は、表示されているエラーメッセージがログに記録されます(ログには「今のところ問題ありません。AuthenticationManagerを直接使用してみます」と記載されていることに注意してください)。
  • Beanとして公開されているAuthenticationManagerを使用してみてください。

コードには、次のようなものを使用するのが最善です。

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class MultiSecurityConfig {
    // Since MultiSecurityConfig does not extend GlobalMethodSecurityConfiguration and
    // define an AuthenticationManager, it will try using the globally defined
    // AuthenticationManagerBuilder to create one

    // The @Enable*Security annotations create a global AuthenticationManagerBuilder 
    // that can optionally be used for creating an AuthenticationManager that is shared
    // The key to using it is to use the @Autowired annotation
    @Autowired
    public void registerSharedAuthentication(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER").and()
                .withUser("admin").password("password").roles("USER", "ADMIN");
    }

    @Configuration
    @Order(1)
    public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
        // Since we didn't specify an AuthenticationManager for this class,
        // the global instance is used


        protected void configure(HttpSecurity http) throws Exception {
            http
                .antMatcher("/api/**")
                .httpBasic();
        }
    }

    @Configuration
    public static class FormWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
        // Since we didn't specify an AuthenticationManager for this class,
        // the global instance is used

        public void configure(WebSecurity web) throws Exception {
            web
                .ignoring()
                    .antMatchers("/static/**","/status");
        }

        protected void configure(HttpSecurity http) throws Exception {
            http
                .authorizeRequests()
                    .anyRequest().hasRole("USER")
                    .and()
                .formLogin()
                    .loginPage("/login")
                    .permitAll();
        }
    }

}

注:これに関するドキュメントは、数日中にリファレンスに追加される予定です。

13
Rob Winch