最新の安定バージョンについては、Spring Security 6.4.2 を使用してください!

構成の移行

次の手順は、HttpSecurityWebSecurityAuthenticationManager の構成方法に関する変更に関連しています。

@Configuration アノテーションを追加

6.0 では、@Configuration が @EnableWebSecurity@EnableMethodSecurity@EnableGlobalMethodSecurity@EnableGlobalAuthentication から削除されています。

これに備えるために、これらのアノテーションのいずれかを使用している場合は、@Configuration を追加する必要がある場合があります。例: @EnableMethodSecurity の変更:

  • Java

@EnableMethodSecurity
public class MyConfiguration {
	// ...
}
  • Kotlin

@EnableMethodSecurity
open class MyConfiguration {
	// ...
}

to:

  • Java

@Configuration
@EnableMethodSecurity
public class MyConfiguration {
	// ...
}
  • Kotlin

@Configuration
@EnableMethodSecurity
open class MyConfiguration {
	// ...
}

新しい requestMatchers メソッドを使用する

Spring Security 5.8 では、antMatchers (Javadoc) mvcMatchers (Javadoc) regexMatchers (Javadoc) メソッドが廃止され、新しい requestMatchers メソッドが採用されました。

新しい requestMatchers メソッドは、authorizeHttpRequestsauthorizeRequests、CSRF 構成、WebSecurityCustomizer、特殊な RequestMatcher メソッドを持つその他の場所に追加されました。非推奨のメソッドは Spring Security 6 で削除されました。

これらの新しいメソッドは、アプリケーションに最適な RequestMatcher 実装を選択するため、より安全なデフォルトを持っています。要約すると、新しいメソッドは、アプリケーションのクラスパスに Spring MVC がある場合は MvcRequestMatcher 実装を選択し、Spring MVC が存在しない場合は AntPathRequestMatcher 実装にフォールバックします (動作を Kotlin の同等のメソッドに合わせます)。

新しいメソッドの使用を開始するには、非推奨のメソッドを新しいメソッドに置き換えることができます。例: 次のアプリケーション構成:

  • Java

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .antMatchers("/api/admin/**").hasRole("ADMIN")
                .antMatchers("/api/user/**").hasRole("USER")
                .anyRequest().authenticated()
            );
        return http.build();
    }

}

次のように変更できます。

  • Java

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                .requestMatchers("/api/user/**").hasRole("USER")
                .anyRequest().authenticated()
            );
        return http.build();
    }

}

クラスパスに Spring MVC があり、mvcMatchers メソッドを使用している場合は、それを新しいメソッドに置き換えることができ、Spring Security が MvcRequestMatcher 実装を選択します。次の構成:

  • Java

@Configuration
@EnableWebSecurity
@EnableWebMvc
public class SecurityConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .mvcMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            );
        return http.build();
    }

}

次と同等です。

  • Java

@Configuration
@EnableWebSecurity
@EnableWebMvc
public class SecurityConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .requestMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            );
        return http.build();
    }

}

MvcRequestMatcher の servletPath プロパティをカスタマイズしている場合、MvcRequestMatcher.Builder を使用して、同じサーブレットパスを共有する MvcRequestMatcher インスタンスを作成できるようになりました。

  • Java

@Configuration
@EnableWebSecurity
@EnableWebMvc
public class SecurityConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .mvcMatchers("/admin").servletPath("/path").hasRole("ADMIN")
                .mvcMatchers("/user").servletPath("/path").hasRole("USER")
                .anyRequest().authenticated()
            );
        return http.build();
    }

}

上記のコードは、MvcRequestMatcher.Builder および requestMatchers メソッドを使用して書き換えることができます。

  • Java

@Configuration
@EnableWebSecurity
@EnableWebMvc
public class SecurityConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
        MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector).servletPath("/path");
        http
            .authorizeHttpRequests((authz) -> authz
                .requestMatchers(mvcMatcherBuilder.pattern("/admin")).hasRole("ADMIN")
                .requestMatchers(mvcMatcherBuilder.pattern("/user")).hasRole("USER")
                .anyRequest().authenticated()
            );
        return http.build();
    }

}

新しい requestMatchers メソッドに問題がある場合は、使用していた RequestMatcher 実装にいつでも戻すことができます。例: AntPathRequestMatcher および RegexRequestMatcher 実装を引き続き使用する場合は、RequestMatcher インスタンスを受け入れる requestMatchers メソッドを使用できます。

  • Java

import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
import static org.springframework.security.web.util.matcher.RegexRequestMatcher.regexMatcher;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .requestMatchers(antMatcher("/user/**")).hasRole("USER")
                .requestMatchers(antMatcher(HttpMethod.POST, "/user/**")).hasRole("ADMIN")
                .requestMatchers(regexMatcher(".*\\?x=y")).hasRole("SPECIAL") // matches /any/path?x=y
                .anyRequest().authenticated()
            );
        return http.build();
    }

}

上記のサンプルでは、AntPathRequestMatcher (Javadoc) および RegexRequestMatcher (Javadoc) の静的ファクトリメソッドを使用して読みやすさを向上させていることに注意してください。

WebSecurityCustomizer インターフェースを使用している場合は、非推奨の antMatchers メソッドを置き換えることができます。

  • Java

@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
	return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2");
}

対応する requestMatchers を使用:

  • Java

@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
	return (web) -> web.ignoring().requestMatchers("/ignore1", "/ignore2");
}

同様に、一部のパスを無視するように CSRF 構成をカスタマイズしている場合は、非推奨のメソッドを requestMatchers メソッドに置き換えることができます。

  • Java

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .csrf((csrf) -> csrf
            .ignoringAntMatchers("/no-csrf")
        );
    return http.build();
}

次のように変更できます。

  • Java

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .csrf((csrf) -> csrf
            .ignoringRequestMatchers("/no-csrf")
        );
    return http.build();
}

新しい securityMatchers メソッドを使用する

Spring Security 5.8 では、HttpSecurity の antMatchersmvcMatchersrequestMatchers メソッドは廃止され、新しい securityMatchers メソッドが採用されました。

これらのメソッドは、requestMatchers メソッドを推奨して廃止された authorizeHttpRequests メソッドと同じではないことに注意してください。ただし、securityMatchers メソッドは、アプリケーションに最適な RequestMatcher 実装を選択するという意味で、requestMatchers メソッドと似ています。要約すると、新しいメソッドは、アプリケーションのクラスパスに Spring MVC がある場合は MvcRequestMatcher 実装を選択し、Spring MVC が存在しない場合は AntPathRequestMatcher 実装にフォールバックします (動作を Kotlin の同等のメソッドに合わせます)。securityMatchers メソッドを追加するもう 1 つの理由は、authorizeHttpRequests の requestMatchers メソッドとの混同を避けるためです。

次の構成:

  • Java

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .antMatcher("/api/**", "/app/**")
        .authorizeHttpRequests((authz) -> authz
            .requestMatchers("/api/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
        );
    return http.build();
}

securityMatchers メソッドを使用して書き換えることができます。

  • Java

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .securityMatcher("/api/**", "/app/**")
        .authorizeHttpRequests((authz) -> authz
            .requestMatchers("/api/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
        );
    return http.build();
}

HttpSecurity 構成でカスタム RequestMatcher を使用している場合:

  • Java

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .requestMatcher(new MyCustomRequestMatcher())
        .authorizeHttpRequests((authz) -> authz
            .requestMatchers("/api/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
        );
    return http.build();
}

public class MyCustomRequestMatcher implements RequestMatcher {
	// ...
}

securityMatcher を使用して同じことができます:

  • Java

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .securityMatcher(new MyCustomRequestMatcher())
        .authorizeHttpRequests((authz) -> authz
            .requestMatchers("/api/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
        );
    return http.build();
}

public class MyCustomRequestMatcher implements RequestMatcher {
	// ...
}

HttpSecurity 構成で複数の RequestMatcher 実装を組み合わせる場合:

  • Java

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .requestMatchers((matchers) -> matchers
            .antMatchers("/api/**", "/app/**")
            .mvcMatchers("/admin/**")
            .requestMatchers(new MyCustomRequestMatcher())
        )
        .authorizeHttpRequests((authz) -> authz
            .requestMatchers("/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
        );
    return http.build();
}

securityMatchers を使用して変更できます。

  • Java

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .securityMatchers((matchers) -> matchers
            .requestMatchers("/api/**", "/app/**", "/admin/**")
            .requestMatchers(new MyCustomRequestMatcher())
        )
        .authorizeHttpRequests((authz) -> authz
            .requestMatchers("/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
        );
    return http.build();
}

RequestMatcher 実装を選択する securityMatchers メソッドに問題がある場合は、いつでも自分で RequestMatcher 実装を選択できます。

  • Java

import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .securityMatchers((matchers) -> matchers
            .requestMatchers(antMatcher("/api/**"), antMatcher("/app/**"))
        )
        .authorizeHttpRequests((authz) -> authz
            .requestMatchers(antMatcher("/api/admin/**")).hasRole("ADMIN")
            .anyRequest().authenticated()
        );
    return http.build();
}

WebSecurityConfigurerAdapter の使用をやめる

SecurityFilterChain Bean を発行する

Spring Security 5.4 は、WebSecurityConfigurerAdapter を継承する代わりに SecurityFilterChain Bean を公開する機能を導入しました。6.0 では、WebSecurityConfigurerAdapter が削除されます。この変更に備えるために、次のような構造を置き換えることができます。

  • Java

  • Kotlin

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authorize) -> authorize
                .anyRequest().authenticated()
            )
            .httpBasic(withDefaults());
    }

}
@Configuration
open class SecurityConfiguration: WebSecurityConfigurerAdapter() {

    @Override
    override fun configure(val http: HttpSecurity) {
        http {
            authorizeHttpRequests {
                authorize(anyRequest, authenticated)
            }

            httpBasic {}
        }
    }

}

with:

  • Java

  • Kotlin

@Configuration
public class SecurityConfiguration {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authorize) -> authorize
                .anyRequest().authenticated()
            )
            .httpBasic(withDefaults());
        return http.build();
    }

}
@Configuration
open class SecurityConfiguration {

    @Bean
    fun filterChain(http: HttpSecurity): SecurityFilterChain {
        http {
            authorizeHttpRequests {
                authorize(anyRequest, authenticated)
            }
            httpBasic {}
        }
        return http.build()
    }

}

WebSecurityCustomizer Bean を発行する

Spring Security 5.4 は、WebSecurityConfigurerAdapterconfigure(WebSecurity web) を置き換えるために WebSecurityCustomizer を導入 [GitHub] (英語) しました。削除の準備として、次のようなコードを置き換えることができます。

  • Java

  • Kotlin

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers("/ignore1", "/ignore2");
    }

}
@Configuration
open class SecurityConfiguration: WebSecurityConfigurerAdapter() {

    override fun configure(val web: WebSecurity) {
        web.ignoring().antMatchers("/ignore1", "/ignore2")
    }

}

with:

  • Java

  • Kotlin

@Configuration
public class SecurityConfiguration {

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2");
    }

}
@Configuration
open class SecurityConfiguration {

    @Bean
    fun webSecurityCustomizer(): WebSecurityCustomizer {
        return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2")
    }

}

AuthenticationManager Bean を発行する

WebSecurityConfigurerAdapter の削除の一環として、configure(AuthenticationManagerBuilder) も削除されます。削除の準備は、それを使用する理由によって異なります。

LDAP 認証

LDAP 認証のサポートに auth.ldapAuthentication() を使用している場合は、次のものを置き換えることができます。

  • Java

  • Kotlin

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .ldapAuthentication()
                .userDetailsContextMapper(new PersonContextMapper())
                .userDnPatterns("uid={0},ou=people")
                .contextSource()
                .port(0);
    }

}
@Configuration
open class SecurityConfiguration: WebSecurityConfigurerAdapter() {

    override fun configure(auth: AuthenticationManagerBuilder) {
        auth
            .ldapAuthentication()
                .userDetailsContextMapper(PersonContextMapper())
                .userDnPatterns("uid={0},ou=people")
                .contextSource()
                .port(0)
    }

}

with:

  • Java

  • Kotlin

@Configuration
public class SecurityConfiguration {
    @Bean
    public EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean() {
        EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean =
            EmbeddedLdapServerContextSourceFactoryBean.fromEmbeddedLdapServer();
        contextSourceFactoryBean.setPort(0);
        return contextSourceFactoryBean;
    }

    @Bean
    AuthenticationManager ldapAuthenticationManager(BaseLdapPathContextSource contextSource) {
        LdapBindAuthenticationManagerFactory factory =
            new LdapBindAuthenticationManagerFactory(contextSource);
        factory.setUserDnPatterns("uid={0},ou=people");
        factory.setUserDetailsContextMapper(new PersonContextMapper());
        return factory.createAuthenticationManager();
    }
}
@Configuration
open class SecurityConfiguration {
    @Bean
    fun contextSourceFactoryBean(): EmbeddedLdapServerContextSourceFactoryBean {
        val contextSourceFactoryBean: EmbeddedLdapServerContextSourceFactoryBean =
            EmbeddedLdapServerContextSourceFactoryBean.fromEmbeddedLdapServer()
        contextSourceFactoryBean.setPort(0)
        return contextSourceFactoryBean
    }

    @Bean
    fun ldapAuthenticationManager(val contextSource: BaseLdapPathContextSource): AuthenticationManager {
        val factory = LdapBindAuthenticationManagerFactory(contextSource)
        factory.setUserDnPatterns("uid={0},ou=people")
        factory.setUserDetailsContextMapper(PersonContextMapper())
        return factory.createAuthenticationManager()
    }
}

JDBC 認証

JDBC 認証のサポートに auth.jdbcAuthentication() を使用している場合は、次のものを置き換えることができます。

  • Java

  • Kotlin

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .build();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build();
        auth.jdbcAuthentication()
            .withDefaultSchema()
                .dataSource(this.dataSource)
                .withUser(user);
    }
}
@Configuration
open class SecurityConfiguration: WebSecurityConfigurerAdapter() {
    @Bean
    fun dataSource(): DataSource {
        return EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .build()
    }

    override fun configure(val auth: AuthenticationManagerBuilder) {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build()
        auth.jdbcAuthentication()
            .withDefaultSchema()
                .dataSource(this.dataSource)
                .withUser(user)
    }
}

with:

  • Java

  • Kotlin

@Configuration
public class SecurityConfiguration {
    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .addScript(JdbcDaoImpl.DEFAULT_USER_SCHEMA_DDL_LOCATION)
            .build();
    }

    @Bean
    public UserDetailsManager users(DataSource dataSource) {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build();
        JdbcUserDetailsManager users = new JdbcUserDetailsManager(dataSource);
        users.createUser(user);
        return users;
    }
}
@Configuration
open class SecurityConfiguration {
    @Bean
    fun dataSource(): DataSource {
        return EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .addScript(JdbcDaoImpl.DEFAULT_USER_SCHEMA_DDL_LOCATION)
            .build()
    }

    @Bean
    fun users(val dataSource: DataSource): UserDetailsManager {
        val user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build()
        val users = JdbcUserDetailsManager(dataSource)
        users.createUser(user)
        return users
    }
}

インメモリ認証

インメモリ認証のサポートに auth.inMemoryAuthentication() を使用している場合は、次のものを置き換えることができます。

  • Java

  • Kotlin

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build();
        auth.inMemoryAuthentication()
            .withUser(user);
    }
}
@Configuration
open class SecurityConfiguration: WebSecurityConfigurerAdapter() {
    override fun configure(val auth: AuthenticationManagerBuilder) {
        val user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build()
        auth.inMemoryAuthentication()
            .withUser(user)
    }
}

with:

  • Java

  • Kotlin

@Configuration
public class SecurityConfiguration {
    @Bean
    public InMemoryUserDetailsManager userDetailsService() {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build();
        return new InMemoryUserDetailsManager(user);
    }
}
@Configuration
open class SecurityConfiguration {
    @Bean
    fun userDetailsService(): InMemoryUserDetailsManager {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build()
        return InMemoryUserDetailsManager(user)
    }
}

@Configuration から @Enable* へのアノテーションの追加

6.0 では、すべての Spring Security の @Enable* アノテーションから @Configuration が削除されました。便利ではあるものの、残りの Spring プロジェクト、特に Spring Framework の @Enable* アノテーションとは一貫性がありませんでした。さらに、Spring Framework での @Configuration(proxyBeanMethods=false) のサポートの導入により、Spring Security の @Enable* アノテーションから @Configuration メタアノテーションを削除し、ユーザーが推奨する構成モードを選択できるようにする別の理由が提供されます。

次のアノテーションでは、@Configuration が削除されました。

  • @EnableGlobalAuthentication

  • @EnableGlobalMethodSecurity

  • @EnableMethodSecurity

  • @EnableReactiveMethodSecurity

  • @EnableWebSecurity

  • @EnableWebFluxSecurity

例: @EnableWebSecurity を使用している場合は、次のように変更する必要があります。

  • Java

@EnableWebSecurity
public class SecurityConfig {
	// ...
}

to:

  • Java

@Configuration
@EnableWebSecurity
public class SecurityConfig {
	// ...
}

上記の他のすべてのアノテーションにも同じことが当てはまります。

その他のシナリオ

より洗練されたものに AuthenticationManagerBuilder を使用している場合は、独自の AuthenticationManager @Bean を公開するか、HttpSecurity#authenticationManager (Javadoc) を使用して AuthenticationManager インスタンスを HttpSecurity DSL に接続できます。