Add WebSecurityConfigurerAdapter Preparation Steps
Issue gh-10902
This commit is contained in:
		
							parent
							
								
									03b407a49a
								
							
						
					
					
						commit
						60e573de26
					
				| 
						 | 
				
			
			@ -3064,6 +3064,462 @@ private fun grantedAuthoritiesMapper(): GrantedAuthoritiesMapper {
 | 
			
		|||
----
 | 
			
		||||
====
 | 
			
		||||
 | 
			
		||||
=== Stop Using `WebSecurityConfigurerAdapter`
 | 
			
		||||
 | 
			
		||||
==== Publish a `SecurityFilterChain` Bean
 | 
			
		||||
 | 
			
		||||
Spring Security 5.4 introduced the capability to publish a `SecurityFilterChain` bean instead of extending `WebSecurityConfigurerAdapter`.
 | 
			
		||||
In 6.0, `WebSecurityConfigurerAdapter` is removed.
 | 
			
		||||
To prepare for this change, you can replace constructs like:
 | 
			
		||||
 | 
			
		||||
====
 | 
			
		||||
.Java
 | 
			
		||||
[source,java,role="primary"]
 | 
			
		||||
----
 | 
			
		||||
@Configuration
 | 
			
		||||
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void configure(HttpSecurity http) throws Exception {
 | 
			
		||||
        http
 | 
			
		||||
            .authorizeHttpRequests((authorize) -> authorize
 | 
			
		||||
                .anyRequest().authenticated()
 | 
			
		||||
            )
 | 
			
		||||
            .httpBasic(withDefaults());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
.Kotlin
 | 
			
		||||
[source,kotlin,role="secondary"]
 | 
			
		||||
----
 | 
			
		||||
@Configuration
 | 
			
		||||
open class SecurityConfiguration: WebSecurityConfigurerAdapter() {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    override fun configure(val http: HttpSecurity) {
 | 
			
		||||
        http {
 | 
			
		||||
            authorizeHttpRequests {
 | 
			
		||||
                authorize(anyRequest, authenticated)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            httpBasic {}
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
====
 | 
			
		||||
 | 
			
		||||
with:
 | 
			
		||||
 | 
			
		||||
====
 | 
			
		||||
.Java
 | 
			
		||||
[source,java,role="primary"]
 | 
			
		||||
----
 | 
			
		||||
@Configuration
 | 
			
		||||
public class SecurityConfiguration {
 | 
			
		||||
 | 
			
		||||
    @Bean
 | 
			
		||||
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
 | 
			
		||||
        http
 | 
			
		||||
            .authorizeHttpRequests((authorize) -> authorize
 | 
			
		||||
                .anyRequest().authenticated()
 | 
			
		||||
            )
 | 
			
		||||
            .httpBasic(withDefaults());
 | 
			
		||||
        return http.build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
.Kotlin
 | 
			
		||||
[source,kotlin,role="secondary"]
 | 
			
		||||
----
 | 
			
		||||
@Configuration
 | 
			
		||||
open class SecurityConfiguration {
 | 
			
		||||
 | 
			
		||||
    @Bean
 | 
			
		||||
    fun filterChain(http: HttpSecurity): SecurityFilterChain {
 | 
			
		||||
        http {
 | 
			
		||||
            authorizeHttpRequests {
 | 
			
		||||
                authorize(anyRequest, authenticated)
 | 
			
		||||
            }
 | 
			
		||||
            httpBasic {}
 | 
			
		||||
        }
 | 
			
		||||
        return http.build()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
====
 | 
			
		||||
 | 
			
		||||
==== Publish an `AuthenticationManager` Bean
 | 
			
		||||
 | 
			
		||||
As part of `WebSecurityConfigurerAdapeter` removal, `configure(AuthenticationManagerBuilder)` is also removed.
 | 
			
		||||
Preparing for its removal will differ based on your reason for using it.
 | 
			
		||||
 | 
			
		||||
===== LDAP Authentication
 | 
			
		||||
 | 
			
		||||
If you are using `auth.ldapAuthentication()` for xref:servlet/authentication/passwords/ldap.adoc[LDAP authentication support], you can replace:
 | 
			
		||||
 | 
			
		||||
====
 | 
			
		||||
.Java
 | 
			
		||||
[source,java,role="primary"]
 | 
			
		||||
----
 | 
			
		||||
@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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
.Kotlin
 | 
			
		||||
[source,kotlin,role="secondary"]
 | 
			
		||||
----
 | 
			
		||||
@Configuration
 | 
			
		||||
open class SecurityConfiguration: WebSecurityConfigurerAdapter() {
 | 
			
		||||
 | 
			
		||||
    override fun configure(auth: AuthenticationManagerBuilder) {
 | 
			
		||||
        auth
 | 
			
		||||
            .ldapAuthentication()
 | 
			
		||||
                .userDetailsContextMapper(PersonContextMapper())
 | 
			
		||||
                .userDnPatterns("uid={0},ou=people")
 | 
			
		||||
                .contextSource()
 | 
			
		||||
                .port(0)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
====
 | 
			
		||||
 | 
			
		||||
with:
 | 
			
		||||
 | 
			
		||||
====
 | 
			
		||||
.Java
 | 
			
		||||
[source,java,role="primary"]
 | 
			
		||||
----
 | 
			
		||||
@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();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
.Kotlin
 | 
			
		||||
[source,kotlin,role="secondary"]
 | 
			
		||||
----
 | 
			
		||||
@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 Authentication
 | 
			
		||||
 | 
			
		||||
If you are using `auth.jdbcAuthentication()` for xref:servlet/authentication/passwords/jdbc.adoc[JDBC Authentication support], you can replace:
 | 
			
		||||
 | 
			
		||||
====
 | 
			
		||||
.Java
 | 
			
		||||
[source,java,role="primary"]
 | 
			
		||||
----
 | 
			
		||||
@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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
.Kotlin
 | 
			
		||||
[source,kotlin,role="secondary"]
 | 
			
		||||
----
 | 
			
		||||
@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
 | 
			
		||||
[source,java,role="primary"]
 | 
			
		||||
----
 | 
			
		||||
@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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
.Kotlin
 | 
			
		||||
[source,kotlin,role="secondary"]
 | 
			
		||||
----
 | 
			
		||||
@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
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
====
 | 
			
		||||
 | 
			
		||||
===== In-Memory Authentication
 | 
			
		||||
 | 
			
		||||
If you are using `auth.inMemoryAuthentication()` for xref:servlet/authentication/passwords/in-memory.adoc[In-Memory Authentication support], you can replace:
 | 
			
		||||
 | 
			
		||||
====
 | 
			
		||||
.Java
 | 
			
		||||
[source,java,role="primary"]
 | 
			
		||||
----
 | 
			
		||||
@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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
.Kotlin
 | 
			
		||||
[source,kotlin,role="secondary"]
 | 
			
		||||
----
 | 
			
		||||
@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
 | 
			
		||||
[source,java,role="primary"]
 | 
			
		||||
----
 | 
			
		||||
@Configuration
 | 
			
		||||
public class SecurityConfiguration {
 | 
			
		||||
    @Bean
 | 
			
		||||
    public InMemoryUserDetailsManager userDetailsService() {
 | 
			
		||||
        UserDetails user = User.withDefaultPasswordEncoder()
 | 
			
		||||
            .username("user")
 | 
			
		||||
            .password("password")
 | 
			
		||||
            .roles("USER")
 | 
			
		||||
            .build();
 | 
			
		||||
        return new InMemoryUserDetailsManager(user);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
.Kotlin
 | 
			
		||||
[source,kotlin,role="secondary"]
 | 
			
		||||
----
 | 
			
		||||
@Configuration
 | 
			
		||||
open class SecurityConfiguration {
 | 
			
		||||
    @Bean
 | 
			
		||||
    fun userDetailsService(): InMemoryUserDetailsManager {
 | 
			
		||||
        UserDetails user = User.withDefaultPasswordEncoder()
 | 
			
		||||
            .username("user")
 | 
			
		||||
            .password("password")
 | 
			
		||||
            .roles("USER")
 | 
			
		||||
            .build()
 | 
			
		||||
        return InMemoryUserDetailsManager(user)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
====
 | 
			
		||||
 | 
			
		||||
===== Other Scenarios
 | 
			
		||||
 | 
			
		||||
If you are using `AuthenticationManagerBuilder` for something more sophisticated, you can xref:servlet/authentication/architecture.adoc#servlet-authentication-authenticationmanager[publish your own `AuthenticationManager` `@Bean`] or wire an `AuthenticationManager` instance into the `HttpSecurity` DSL with {security-api-url}org/springframework/security/config/annotation/web/builders/HttpSecurity.html#authenticationManager(org.springframework.security.authentication.AuthenticationManager)[`HttpSecurity#authenticationManager`].
 | 
			
		||||
 | 
			
		||||
==== Publish a `WebSecurityCustomizer` Bean
 | 
			
		||||
 | 
			
		||||
Spring Security 5.4 https://github.com/spring-projects/spring-security/issues/8978[introduced `WebSecurityCustomizer`] to replace `configure(WebSecurity web)` in `WebSecurityConfigurerAdapter`.
 | 
			
		||||
To prepare for its removal, you can replace code like the following:
 | 
			
		||||
 | 
			
		||||
====
 | 
			
		||||
.Java
 | 
			
		||||
[source,java,role="primary"]
 | 
			
		||||
----
 | 
			
		||||
@Configuration
 | 
			
		||||
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void configure(WebSecurity web) {
 | 
			
		||||
        web.ignoring().antMatchers("/ignore1", "/ignore2");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
.Kotlin
 | 
			
		||||
[source,kotlin,role="secondary"]
 | 
			
		||||
----
 | 
			
		||||
@Configuration
 | 
			
		||||
open class SecurityConfiguration: WebSecurityConfigurerAdapter() {
 | 
			
		||||
 | 
			
		||||
    override fun configure(val web: WebSecurity) {
 | 
			
		||||
        web.ignoring().antMatchers("/ignore1", "/ignore2")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
====
 | 
			
		||||
 | 
			
		||||
with:
 | 
			
		||||
 | 
			
		||||
====
 | 
			
		||||
.Java
 | 
			
		||||
[source,java,role="primary"]
 | 
			
		||||
----
 | 
			
		||||
@Configuration
 | 
			
		||||
public class SecurityConfiguration {
 | 
			
		||||
 | 
			
		||||
    @Bean
 | 
			
		||||
    public WebSecurityCustomizer webSecurityCustomizer() {
 | 
			
		||||
        return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
.Kotlin
 | 
			
		||||
[source,kotlin,role="secondary"]
 | 
			
		||||
----
 | 
			
		||||
@Configuration
 | 
			
		||||
open class SecurityConfiguration {
 | 
			
		||||
 | 
			
		||||
    @Bean
 | 
			
		||||
    fun webSecurityCustomizer(): WebSecurityCustomizer {
 | 
			
		||||
        return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
----
 | 
			
		||||
====
 | 
			
		||||
 | 
			
		||||
== Reactive
 | 
			
		||||
 | 
			
		||||
=== Use `AuthorizationManager` for Method Security
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue