Skip to main content

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):

Spring Security Internal Architecture

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:

Clic para ampliar

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:

  1. Calls the UserDetailsService to fetch the user from persistent storage.
  2. Uses the PasswordEncoder to check whether the submitted plain password matches the stored database hash.
  3. If matching, constructs and returns a fully authenticated and validated Authentication object.

E. UserDetailsService and UserDetails​

  • UserDetailsService: A functional interface with a single method:
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
    Serves as the adapter between Spring Security and your persistence layer (JPA Repositories).
  • 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();

Self-Assessment Quiz​

Cargando cuestionario...