Spring Security
Spring Boot 3
Java
Authentication
Web Application Security

Spring Security in Spring Boot 3

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Spring Boot 3 uses the modern Spring Security style built around beans such as SecurityFilterChain instead of the old WebSecurityConfigurerAdapter. The framework still solves the same core problems: authentication, authorization, password encoding, and protection around HTTP endpoints. What changed is the configuration model, which is now more explicit and composable.

Define a SecurityFilterChain

In Boot 3, the standard entry point for HTTP security is a SecurityFilterChain bean.

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

This style makes the request rules visible in one place and avoids deep inheritance-based configuration.

Authentication Still Needs a Source of Users

Authorizing requests is only part of security. Spring also needs a way to authenticate users. For small examples, an in-memory user store is enough.

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
7UserDetailsService userDetailsService(PasswordEncoder encoder) {
8    return new InMemoryUserDetailsManager(
9        User.withUsername("admin")
10            .password(encoder.encode("secret"))
11            .roles("ADMIN")
12            .build()
13    );
14}

In real applications, this usually becomes a database-backed UserDetailsService, an external identity provider, or token-based authentication.

Match Security Style to the Application Type

Spring Security configuration should reflect whether the application is session-based, API-based, or token-based. A browser app with form login has different requirements from a stateless JSON API.

For a stateless API, you typically disable session-oriented assumptions and add token processing instead of form login. The principle is simple: configure only the security mechanisms that fit the transport and client model you actually use.

Password Encoding Is Not Optional

Boot 3 and Spring Security expect encoded passwords. Storing raw passwords is not only insecure, it also conflicts with how the framework is designed to compare credentials safely.

That is why a PasswordEncoder bean belongs in even the simplest example. It keeps the sample aligned with real application behavior rather than teaching a shortcut that should not survive into production.

Authorization Rules Deserve Precision

Request matching is easy to make too broad. It is tempting to permit whole path trees during development and then forget to tighten them. A better habit is to describe the smallest public surface and require authentication for everything else.

That default-deny posture is one of the strongest practical habits in Spring Security work. The framework is powerful, but precise rules matter more than clever rules.

Security Configuration Is Only One Layer

HTTP security does not replace method-level checks, validation, secure password storage, or careful handling of tokens and sessions. It is the web boundary, not the whole security story.

That matters because misconfigured authorization often gets all the blame, while the real issue is an application design assumption outside the filter chain.

Keeping that boundary clear makes security reviews more honest. A clean filter chain is valuable, but it does not excuse weak domain rules deeper in the application.

Common Pitfalls

  • Looking for WebSecurityConfigurerAdapter in Boot 3 instead of defining beans such as SecurityFilterChain.
  • Adding authentication rules without configuring any real user source.
  • Using overly broad permitAll patterns during development and forgetting to remove them.
  • Skipping password encoding in sample code and then carrying that mistake forward.
  • Applying browser-oriented defaults to a stateless API without thinking through the client model.

Summary

  • Spring Boot 3 configures web security with beans such as SecurityFilterChain.
  • Authentication still needs a user source such as an in-memory or database-backed service.
  • Password encoding should be part of even basic setups.
  • Match the security style to whether the app is browser-based or API-based.
  • Keep authorization rules narrow and explicit.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.