Handling Spring Security Version Differences (Spring Security 5 vs. Spring Security 6)
In modern Spring Boot development, security architecture evolves continuously across major release cycles. While core security concepts—such as authentication, authorization, filter chains, and security contexts—remain fundamentally identical, the concrete configuration syntax differs significantly between Spring Boot 2.x (Spring Security 5.x) and Spring Boot 3.x (Spring Security 6.x). This guide details how to navigate these version differences, understand the paradigm shift from class extension to Bean-based configuration, and run the security module successfully regardless of your project's version.
1. Understanding the Version Discrepancy Problem
When learning or implementing Spring Security, developers often encounter build failures or compilation errors when running code written for Spring Boot 2.x on a Spring Boot 3.x runtime environment.
Primary Causes of Version Conflicts
- Deprecation & Removal of
WebSecurityConfigurerAdapter: In Spring Security 5.7+, extendingWebSecurityConfigurerAdapterwas deprecated, and in Spring Security 6.0 (Spring Boot 3.0+), it was removed entirely. - Namespace Migration (
javaxtojakarta): Spring Boot 3.0 transitioned from Java EE (javax.servlet.*) to Jakarta EE (jakarta.servlet.*). - Shift to Lambda DSL: Spring Security 6 enforces functional/lambda style configurations for
HttpSecurityto improve readability and prevent method chaining misconfigurations.
Note: If you are using the exact Java and Spring Boot versions used in a legacy lecture setup, your code will compile without modifications. However, if you generate a project using Spring Initializr today, Spring Boot 3.x is selected by default, requiring the updated configuration style.
2. Core Mental Model: Conceptual Consistency vs. Syntax Evolution
To master Spring Security across different versions, separate the conceptual architecture from the implementation syntax.
Real-Life Analogy
Imagine driving a car from the 2010s versus a modern electric vehicle:
- The Core Mechanics: Both vehicles require a steering wheel, accelerator, brakes, traffic signal compliance, and side mirrors to operate safely.
- The Control Interface: The physical ignition key might be replaced by a digital start button or a smartphone key, and mechanical dials might become touchscreen menus.
Similarly, in Spring Security:
- The Core Concept: Incoming HTTP requests pass through a chain of security filters (Filter Chain). Filters inspect credentials (Authentication) and verify role permissions (Authorization) before allowing access to a controller endpoint.
- The Syntax Interface: Spring Security 5 used inheritance (
extends WebSecurityConfigurerAdapter). Spring Security 6 uses component composition (registering a@Beanof typeSecurityFilterChain).
3. The Legacy Approach: Spring Security 5 (Spring Boot 2.x)
In Spring Boot 2.x, security configurations relied heavily on object-oriented inheritance by extending the abstract class WebSecurityConfigurerAdapter and overriding its configure(HttpSecurity http) method.
Legacy Configuration Pattern
package com.example.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class LegacySecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/public/**", "/login").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.permitAll()
.and()
.httpBasic();
}
}
Limitations of the Legacy Style
- Tight Coupling: Forcing configuration classes to inherit from
WebSecurityConfigurerAdaptercreated rigid class hierarchies. - Method Overloading Confusion: Multiple overloaded
configure()methods (forAuthenticationManagerBuilder,WebSecurity, andHttpSecurity) often led to configuration mistakes. - Imperative Chaining: Chaining methods with
.and()made complex security rules hard to parse visually.
4. The Modern Approach: Spring Security 6 (Spring Boot 3.x)
Spring Security 6 replaces class inheritance with a component-oriented Bean model. Instead of overriding a base class method, you declare a public @Bean that returns a SecurityFilterChain.
Modern Configuration Pattern
package com.example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class ModernSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// Disable CSRF using lambda syntax
.csrf(csrf -> csrf.disable())
// Define request authorization rules
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**", "/login").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
// Configure authentication mechanisms
.formLogin(form -> form.permitAll())
.httpBasic(httpBasic -> {});
return http.build();
}
}
Key Architectural Improvements
- Decoupled Bean Registration:
SecurityFilterChainis managed directly by the Spring IoC container. - Explicit Request Matchers:
.requestMatchers()replaces.antMatchers()and.mvcMatchers(), providing safer default path matching. - Lambda DSL Focus: Eliminates
.and()calls by scoping configurations cleanly inside functional lambdas.
5. Architectural Comparison & Migration Walkthrough
Structural Request Flow
Both versions intercept incoming web requests before they reach your @RestController, processing them through an ordered series of security filters:
Paradigm Comparison Table
6. Practical Debugging & Workflow Checklist
If your Spring Security configuration fails to compile or start, run through this step-by-step diagnostic checklist to identify and fix version mismatches.
Step 1: Identify Your Active Spring Boot Version
Check your build configuration file to determine which major version family you are running:
-
Maven (
pom.xml):XML<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.1</version> <!-- Version 3.x indicates Spring Security 6 --> </parent> -
Gradle (
build.gradle):GROOVYplugins { id 'org.springframework.boot' version '3.2.1' }
Step 2: Choose the Correct Security Class Strategy
-
Scenario A (Matching Lecture Version / Spring Boot 2.x):
- Continue following the lecture step-by-step.
- Keep using the legacy
WebSecurityConfigurerAdapterconfiguration class.
-
Scenario B (Latest Environment / Spring Boot 3.x):
- Focus on understanding the core theoretical concepts presented in the lecture (e.g., how authentication tokens work, filter order, role checks).
- Do not copy legacy configuration syntax directly.
- Instead, download or copy the modern
SpringSecurityConfigclass provided for Spring Security 6 and add it to your project's configuration package.
7. Summary and Key Takeaways
- Core Concepts Never Change: Fundamental security principles—such as authenticating users, restricting path authorization based on roles, and routing through filter chains—are identical across all Spring Security versions.
- Inheritance is Removed: Spring Security 6 completely removes
WebSecurityConfigurerAdapter. Configurations now use standalone@Configurationclasses. - Bean-Driven Security: Modern configurations register a
@Beanof typeSecurityFilterChainthat builds and returns theHttpSecurityinstance. - Lambda DSL Standard: Spring Security 6 relies on lambda expressions (e.g.,
csrf -> csrf.disable()), replacing chained method calls connected with.and(). - Path Matcher Consolidation: Replace deprecated
.antMatchers()methods with.requestMatchers(). - Package Migration: Spring Boot 3 projects require
jakarta.servlet.*package imports instead of legacyjavax.servlet.*imports. - Smart Workflow Strategy: When following course material recorded on older versions, focus on the underlying architectural concepts during the lecture, but use the updated configuration template corresponding to your installed Spring Boot runtime version.