Spring Boot 2.7.0
WebSecurityConfigurerAdapter
Spring Security
Java
Upgrade Guide

Upgrading the deprecated WebSecurityConfigurerAdapter in Spring Boot 2.7.0

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Spring Boot 2.7.0 marks a significant change in how security configurations are handled. The WebSecurityConfigurerAdapter, which was long used to configure web security, has been deprecated. This shift signals Spring's move towards a more flexible and modular approach to security configuration. Developers must understand how to upgrade old implementations to the new paradigm. This article will guide you through these updates and provide comprehensive examples to illustrate the changes.

Background

WebSecurityConfigurerAdapter was a convenient base class for creating custom security configurations by overriding specific hook methods such as configure(HttpSecurity http) and configure(AuthenticationManagerBuilder auth). However, this approach forced developers into using an inheritance-based model, which can be restrictive and against the modern composition-over-inheritance principle in software design.

Understanding the New Approach

The deprecation of WebSecurityConfigurerAdapter pushes developers towards using simpler, component-based configurations that rely heavily on lambda expressions and builders. The new approach promotes a more explicit and finer-grained security configuration.

Key Components Introduced:

  1. SecurityFilterChain Configuration:
    • Introduced to define a custom filter chain without extending any class.
    • Uses @Bean annotated methods to define security filters.
  2. Creating a Password Encoder:
    • A fresh necessity because the old adapter's convention on password encoding isn’t available.
  3. UserDetailsService Bean:
    • Direct and flexible approach to register user details.
  4. HttpSecurity Customizer:
    • Offers more control and precision with HttpSecurity configurations.

Upgrading Your Security Configuration

Step-by-Step Example of Transitioning

Let's consider an application that initially used WebSecurityConfigurerAdapter.

java
1// Deprecated approach with WebSecurityConfigurerAdapter
2import org.springframework.security.config.annotation.web.builders.HttpSecurity;
3import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
4
5public class SecurityConfig extends WebSecurityConfigurerAdapter {
6    @Override
7    protected void configure(HttpSecurity http) throws Exception {
8        http
9            .authorizeRequests()
10                .antMatchers("/admin/**").hasRole("ADMIN")
11                .anyRequest().authenticated()
12            .and()
13            .formLogin()
14                .permitAll();
15    }
16}

Upgraded Version:

With the new approach, instead of extending WebSecurityConfigurerAdapter, you'll directly define beans:

java
1import org.springframework.context.annotation.Bean;
2import org.springframework.security.config.annotation.web.builders.HttpSecurity;
3import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
4import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
5import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
6import org.springframework.security.crypto.password.PasswordEncoder;
7import org.springframework.security.web.SecurityFilterChain;
8
9@EnableWebSecurity
10public class SecurityConfig {
11
12    @Bean
13    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
14        http
15            .authorizeHttpRequests(authorize -> authorize
16                .requestMatchers("/admin/**").hasRole("ADMIN")
17                .anyRequest().authenticated()
18            )
19            .formLogin(withDefaults());
20        return http.build();
21    }
22
23    @Bean
24    public PasswordEncoder passwordEncoder() {
25        return new BCryptPasswordEncoder();
26    }
27}

Key Differences to Note

FeatureWebSecurityConfigurerAdapterNew Approach
Base ClassExtends WebSecurityConfigurerAdapterNo base class extension
Configuration MethodOverride configure()Define SecurityFilterChain Bean
Password EncodingConfigured within overridden methodSeparate PasswordEncoder Bean
AuthenticationCustomize within adapterUse AuthenticationManager Bean if needed
URI MatchingantMatchers()requestMatchers()
FlexibilityLess modularPromotes modular configuration

Best Practices for the New Approach

  • Embrace Lambda Expressions: Leverage lambda expressions for concise security configurations.
  • Define Beans Explicitly: This shift enforces a clear declaration of components, aligning with Spring Boot's convention-over-configuration philosophy.
  • Test Thoroughly: Security configurations might behave differently based on subtle changes. Rigorous testing is essential.

Subtopics

Handling User Details Service

Defining a UserDetailsService is crucial for setting up custom user details:

java
1import org.springframework.context.annotation.Bean;
2import org.springframework.security.core.userdetails.User;
3import org.springframework.security.core.userdetails.UserDetailsService;
4import org.springframework.security.provisioning.InMemoryUserDetailsManager;
5
6@Bean
7public UserDetailsService userDetailsService() {
8    User.UserBuilder users = User.builder();
9    return new InMemoryUserDetailsManager(
10        users.username("user").password(passwordEncoder().encode("password")).roles("USER").build(),
11        users.username("admin").password(passwordEncoder().encode("password")).roles("USER", "ADMIN").build()
12    );
13}

Customizing Authentication Management

For more complex scenarios where AuthenticationManager needs customization:

java
1import org.springframework.context.annotation.Bean;
2import org.springframework.security.authentication.AuthenticationManager;
3import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
4
5@Bean
6public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
7    return authenticationConfiguration.getAuthenticationManager();
8}

Conclusion

Transitioning from WebSecurityConfigurerAdapter involves a structurally different approach, but it provides greater flexibility and aligns with modern software development principles. The new method simplifies security configurations by leveraging Spring's bean management and dependency injection capability while adhering strictly to the separation of concerns.

Adopting these changes early will not only keep your applications secure and up-to-date but will also open up avenues for more flexible security architecture in your applications.


Course illustration
Course illustration

All Rights Reserved.