Spring Boot
WebSecurityConfigurerAdapter
Security Configuration
Multiple Patterns
Spring Security

Multiple WebSecurityConfigurerAdapter in spring boot for multiple patterns

Master System Design with Codemia

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

Introduction

Older Spring Security applications often used multiple WebSecurityConfigurerAdapter classes to apply different security rules to different URL patterns. The basic idea is to scope each configuration to a matcher, then order those configurations so the most specific one runs first.

That approach still appears in legacy Spring Boot codebases even though new projects should usually use SecurityFilterChain instead.

How Multiple Configurers Work

When you define more than one security adapter, Spring evaluates them in order and applies the first configuration whose request matcher fits the incoming request. That means two things matter immediately:

  • each adapter must match only the URLs it is responsible for
  • the order must go from most specific to most general

A common split looks like this:

  • '/api/** uses HTTP Basic or token-based auth'
  • '/admin/** requires an admin role'
  • everything else uses form login

If a broad matcher runs too early, it can swallow requests meant for a narrower configuration.

Legacy Example With Two Adapters

Here is a classic adapter-based setup:

java
1import org.springframework.context.annotation.Configuration;
2import org.springframework.core.annotation.Order;
3import org.springframework.security.config.annotation.web.builders.HttpSecurity;
4import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
5import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
6
7@Configuration
8@EnableWebSecurity
9public class SecurityConfig {
10
11    @Configuration
12    @Order(1)
13    public static class ApiSecurityConfig extends WebSecurityConfigurerAdapter {
14        @Override
15        protected void configure(HttpSecurity http) throws Exception {
16            http
17                .antMatcher("/api/**")
18                .authorizeRequests()
19                    .anyRequest().hasRole("API_USER")
20                .and()
21                .httpBasic();
22        }
23    }
24
25    @Configuration
26    public static class FormSecurityConfig extends WebSecurityConfigurerAdapter {
27        @Override
28        protected void configure(HttpSecurity http) throws Exception {
29            http
30                .authorizeRequests()
31                    .antMatchers("/login", "/public/**").permitAll()
32                    .anyRequest().authenticated()
33                .and()
34                .formLogin();
35        }
36    }
37}

The first adapter handles only /api/** requests because of antMatcher. The second acts as the fallback configuration for everything else.

Why Order Matters

Suppose the form-login configuration were evaluated before the API configuration. Then a request to /api/orders might be caught by the general rule and redirected to a login page instead of getting HTTP Basic authentication.

That is why ordering is not optional here. Specific rules must come before fallback rules, or the entire split-security design collapses into confusing behavior.

A useful mental model is "first matching security configuration wins."

The Modern Equivalent

WebSecurityConfigurerAdapter is deprecated in modern Spring Security. New code should define multiple SecurityFilterChain beans instead. The concept is the same even though the API is newer:

java
1import org.springframework.context.annotation.Bean;
2import org.springframework.context.annotation.Configuration;
3import org.springframework.core.annotation.Order;
4import org.springframework.security.config.Customizer;
5import org.springframework.security.config.annotation.web.builders.HttpSecurity;
6import org.springframework.security.web.SecurityFilterChain;
7
8@Configuration
9public class SecurityConfig {
10
11    @Bean
12    @Order(1)
13    SecurityFilterChain apiChain(HttpSecurity http) throws Exception {
14        http
15            .securityMatcher("/api/**")
16            .authorizeHttpRequests(auth -> auth.anyRequest().hasRole("API_USER"))
17            .httpBasic(Customizer.withDefaults());
18        return http.build();
19    }
20
21    @Bean
22    SecurityFilterChain appChain(HttpSecurity http) throws Exception {
23        http
24            .authorizeHttpRequests(auth -> auth
25                .requestMatchers("/login", "/public/**").permitAll()
26                .anyRequest().authenticated())
27            .formLogin(Customizer.withDefaults());
28        return http.build();
29    }
30}

If you are maintaining legacy code, understanding the adapter approach is still valuable. If you are writing new code, prefer filter chains.

Common Pitfalls

The most common mistake is forgetting to scope a configuration. Without antMatcher or another request matcher, one adapter can accidentally apply to the whole application and shadow every other one.

Another pitfall is getting the order wrong. The more general configuration must not come before the narrow one.

A third issue is mixing browser-style and API-style expectations. Redirects, CSRF handling, session state, and authentication entry points often differ between UI traffic and API traffic. Splitting configurations helps, but only if the boundaries are clear.

Summary

  • Multiple WebSecurityConfigurerAdapter classes were a legacy way to secure different URL patterns differently.
  • Each adapter needs a clear matcher so it handles only the intended requests.
  • Ordering is essential because the first matching configuration wins.
  • Broad fallback rules should come after specific API or admin rules.
  • New Spring Security code should usually use multiple SecurityFilterChain beans instead.

Course illustration
Course illustration

All Rights Reserved.