Master Spring Security 5.7+ Config: From WebSecurityConfigurerAdapter to SecurityFilterChain
This guide explains how Spring Security configuration changed after version 5.7, covering the shift from WebSecurityConfigurerAdapter to SecurityFilterChain beans, multiple filter chain setup, in‑memory user definitions, custom authorization decisions, and shared authentication components, with full code examples.
Environment
Spring Boot 2.7.12 with JDK 21.
1. Introduction
Spring Security is a framework that provides authentication, authorization and protection against common attacks for both imperative and reactive applications. Its core consists of two modules:
Authentication : the process of establishing the identity of a principal (user, device, etc.) typically by verifying a username and password.
Authorization : after authentication, the system checks whether the principal has permission to access a requested resource, often based on roles.
2. Security Configuration
2.1 Configuration style
Before Spring Security 5.7, custom security configuration was done by extending WebSecurityConfigurerAdapter:
@Component
public class SecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
// ...
}
}Since 5.7, the recommended approach is to define a SecurityFilterChain bean:
@Configuration
public class SecurityConfig {
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
SecurityFilterChain controllerFilterChain(HttpSecurity http) throws Exception {
// ...
return http.build();
}
}2.2 Multiple filter chains
Multiple filter chains can be configured in a single configuration class, each with its own @Order to set priority:
@Configuration
public class SecurityConfig {
@Bean
@Order(1)
SecurityFilterChain controllerFilterChain(HttpSecurity http) {
// intercept /demos/**, /login, /logout
http.requestMatchers(m -> m.antMatchers("/demos/**", "/login", "/logout"));
http.authorizeHttpRequests().antMatchers("/**").authenticated();
http.formLogin(Customizer.withDefaults());
return http.build();
}
@Bean
@Order(2)
SecurityFilterChain managementSecurityFilterChain(HttpSecurity http) throws Exception {
// intercept /ac/**
http.requestMatchers(m -> m.antMatchers("/ac/**"));
http.formLogin(Customizer.withDefaults());
return http.build();
}
}The chain with the lower @Order value is evaluated first. Requests not matching any explicit pattern are permitted.
2.3 User authentication configuration
Before 5.7, in‑memory users were defined in configure(AuthenticationManagerBuilder):
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.passwordEncoder(NoOpPasswordEncoder.getInstance())
.withUser("admin")
.password("123123")
.authorities(Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN")));
}
}From 5.7 onward, the same can be achieved inside a SecurityFilterChain bean:
@Configuration
public class SecurityConfig {
@Bean
@Order(0)
SecurityFilterChain controllerFilterChain(HttpSecurity http) throws Exception {
AuthenticationManagerBuilder builder = http.getSharedObject(AuthenticationManagerBuilder.class);
builder.inMemoryAuthentication()
.passwordEncoder(NoOpPasswordEncoder.getInstance())
.withUser("admin")
.password("123123")
.authorities(Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN")));
return http.build();
}
}2.4 Authorization method
After 5.7, authorization is typically expressed with authorizeHttpRequests, which adds an AuthorizationFilter to the chain to evaluate permissions.
2.5 Custom authorization decision
For fine‑grained URI matching, a custom AuthorizationManager can be supplied:
@Bean
public SecurityFilterChain apiSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(registry -> {
registry.antMatchers("/users/{id}").access(new AuthorizationManager<RequestAuthorizationContext>() {
@Override
public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext object) {
// obtain path variable "id" and allow only if it equals "666"
Map<String, String> variables = // ...
return new AuthorityAuthorizationDecision(variables.get("id").equals("666"),
Arrays.asList(new SimpleGrantedAuthority("D")));
}
});
});
return http.build();
}2.6 Global authentication
If several filter chains share the same user store, a common UserDetailsService or AuthenticationProvider bean can be defined:
@Bean
UserDetailsService userDetailsService() {
return new UserDetailsService() {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return null;
}
};
}
@Bean
AuthenticationProvider authenticationProvider() {
return new AuthenticationProvider() {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
return null;
}
@Override
public boolean supports(Class<?> authentication) {
return false;
}
};
}Hope this article helps you configure Spring Security with the new style.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
