Spring Security Internal Architecture
To master Spring Security rather than relying on copy-pasting configurations, we must examine how the framework intercepts and processes every incoming HTTP request inside the Servlet container (Apache Tomcat):
1. The HTTP Request Lifecycle in Detail
When a client sends a request to an endpoint in our application, the request interacts sequentially with the components of Spring Security. Trace the step-by-step lifecycle below:
2. Anatomy of Architectural Components
A. Security Filter Chain (SecurityFilterChain)
In standard Java Web (Jakarta EE), Filters are interceptors executed before a request reaches the primary Servlet (DispatcherServlet). Spring Security registers an ordered chain of specialized filters (SecurityFilterChain managed by FilterChainProxy). Each filter handles a specific concern (CORS validation, CSRF protection, capturing login credentials, or validating URL path permissions).
B. Authentication Filter (UsernamePasswordAuthenticationFilter)
This filter intercepts login attempts. It reads username and password parameters from the request body (in forms) or from the Authorization: Basic ... header. It wraps these credentials into an unauthenticated UsernamePasswordAuthenticationToken and delegates it to the central manager.
C. AuthenticationManager (ProviderManager)
The core interface defining the authentication contract (authenticate(Authentication)). In practice, Spring Security uses its default implementation: ProviderManager. The manager does not perform verification itself; instead, it acts as a coordinator, iterating through a list of registered providers until finding one capable of supporting that credential type.
D. AuthenticationProvider (DaoAuthenticationProvider)
The component containing the concrete verification logic. For applications backed by relational databases, Spring utilizes DaoAuthenticationProvider. This provider:
- Calls the
UserDetailsServiceto fetch the user from persistent storage. - Uses the
PasswordEncoderto check whether the submitted plain password matches the stored database hash. - If matching, constructs and returns a fully authenticated and validated
Authenticationobject.
E. UserDetailsService and UserDetails
UserDetailsService: A functional interface with a single method:Serves as the adapter between Spring Security and your persistence layer (JPA Repositories).UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;UserDetails: The abstraction representing a user identity in Spring Security. Provides standard methods to query credentials and account state:getUsername(): The account username.getPassword(): The stored password hash.getAuthorities(): Collection of assigned permissions and roles (GrantedAuthority).isAccountNonExpired(),isAccountNonLocked(),isEnabled(): Account lifecycle status flags.
F. PasswordEncoder
The interface responsible for processing and validating passwords:
public interface PasswordEncoder {
String encode(CharSequence rawPassword);
boolean matches(CharSequence rawPassword, String encodedPassword);
}
In modern production environments, the mandatory standard implementation is BCryptPasswordEncoder.
G. SecurityContextHolder and SecurityContext
Once a user is successfully authenticated, the filter stores the validated Authentication instance inside the SecurityContextHolder:
SecurityContextHolder.getContext().setAuthentication(authenticatedToken);
The SecurityContextHolder stores this information using ThreadLocal, binding the security context to the execution thread of the active request. Consequently, any controller or service can inspect the authenticated user at any point:
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String currentUsername = auth.getName();