Hello! Welcome to the first lesson in our module on "Spring Security & REST API Design."
In our last lesson, we explored how Spring uses AOP proxies to intercept method calls and apply cross-cutting concerns like transaction management. This "interception" model is a powerful pattern you'll see throughout the Spring ecosystem.
Today, we'll see that same pattern applied at a different level. Your learning outcome is to explain Spring Security's filter chain architecture and the role of the SecurityContextHolder. We will move from intercepting Java method calls to intercepting incoming HTTP requests. A solid grasp of this architecture is non-negotiable for senior-level interviews, as it forms the bedrock of how security is enforced in virtually all Spring web applications.
1. The Foundation: Servlet Filters
Before diving into Spring Security itself, we must start with the technology it's built upon: Servlet Filters. A Servlet Filter is a standard Java EE component that intercepts incoming HTTP requests and outgoing responses. Filters are chained together, forming a FilterChain. Each filter in the chain can inspect or modify the request before passing it to the next filter, and eventually to the target servlet (in Spring MVC, this is the DispatcherServlet).
This provides a perfect mechanism for handling cross-cutting concerns at the web layer, like logging, compression, and, most importantly, security.
Architecture :: Spring Security
To understand this foundational concept, let's review the official Spring Security documentation, which provides a concise explanation of Servlet Filters.
Please read the section titled 'A Review of Filters'. Focus on understanding how a FilterChain processes a request and the role of the chain.doFilter(request, response) call.
The key takeaway is that filters form a pipeline. A request enters the pipeline and passes through each filter in order. A filter can decide to:
- Perform some action and then pass the request down the chain.
- Block the request entirely (for example, if a security check fails).
- Modify the request or response before passing it along.
2. The Bridge: DelegatingFilterProxy and FilterChainProxy
Now, a challenge arises. Servlet Filters are managed by the Servlet Container (like Tomcat), but the rich components needed for security (services, repositories, etc.) are managed by Spring's ApplicationContext. How do we connect these two worlds?
Spring's solution is a special filter called DelegatingFilterProxy.
DelegatingFilterProxy: This is a standard Servlet Filter registered with the container. Its only job is to find a Spring bean in theApplicationContextthat is also aFilterand delegate the request to it. It acts as a bridge.
The Spring bean it delegates to is typically the FilterChainProxy.
FilterChainProxy: This is the powerhouse of Spring Security. It's a single, special filter that contains the entire security logic. Internally, it manages a list of one or moreSecurityFilterChaininstances. It decides which security chain to apply based on the request URI.

🔒 Spring Security Architecture: The Bigger Picture Explained! 🚀
To see how these components connect, let's watch a video that walks through the architecture, starting from the filter chain concept we just discussed.
Watch the segment from 07:59 to 12:18. The presenter does an excellent job of explaining the need for the DelegatingFilterProxy to bridge the Servlet API and Spring context, and then introduces the FilterChainProxy as the container for the actual security filters.
In summary, the flow is:
Client Request -> Servlet Container -> DelegatingFilterProxy -> Spring ApplicationContext -> FilterChainProxy -> SecurityFilterChain
3. Inside the SecurityFilterChain
The FilterChainProxy determines which SecurityFilterChain should handle a request. A SecurityFilterChain is an ordered list of security-specific filters, each with a distinct responsibility. By default, Spring Boot auto-configures a standard chain that includes several important filters.
When you add spring-boot-starter-security to your project, you get a secure-by-default setup. Every request must be authenticated. This is enforced by a default chain of filters.
Here are some of the most important filters you'll find in a typical chain:
CsrfFilter: Protects against Cross-Site Request Forgery attacks.UsernamePasswordAuthenticationFilter: The default filter for processing username/password from a login form.BasicAuthenticationFilter: Handles HTTP Basic authentication.ExceptionTranslationFilter: Catches security-related exceptions (likeAccessDeniedException) thrown further down the chain and translates them into appropriate HTTP responses (like a 403 Forbidden or a redirect to a login page).AuthorizationFilter: Responsible for determining if an authenticated user is authorized to access a specific resource.
🔒 Spring Security Architecture: The Bigger Picture Explained! 🚀
Seeing this in action is the best way to understand it. The same video includes a debugging session that steps through the filter chain.
Watch from 13:43 to 17:07. Pay close attention as the debugger inspects the FilterChainProxy and you see the list of actual filter beans. The presenter specifically highlights the UsernamePasswordAuthenticationFilter, which is active in the default form-login configuration.
Understanding this ordered chain is critical. For example, an authentication filter must run before an authorization filter. It makes no sense to check if a user is authorized before you even know who they are.
4. Storing the Authenticated User: SecurityContextHolder
Once a filter (like UsernamePasswordAuthenticationFilter) successfully authenticates a user, where does it store this information so that the rest of the application can access it?
This is the job of the SecurityContextHolder.
-
AuthenticationObject: After successful authentication, anAuthenticationobject is created. This object contains the user's identity (principal), their credentials (which are usually cleared immediately after authentication), and a list of their granted authorities (roles or permissions). -
SecurityContext: This is a simple container that holds oneAuthenticationobject. -
SecurityContextHolder: This is the central component for accessing theSecurityContext. By default, it uses aThreadLocalstrategy. This means theSecurityContext(and thus theAuthenticationobject) is bound to the current execution thread. As a single request is processed by a single thread, this makes the security information available everywhere in your code during that request's lifecycle—from your services to your controllers—without needing to pass it as a method parameter.
At the end of the request, a filter (SecurityContextHolderFilter) ensures the ThreadLocal is cleared to prevent memory leaks and issues with thread reuse.

Servlet Authentication Architecture :: Spring Security
The official documentation provides the most precise definition of these components.
Read the sections titled 'SecurityContextHolder', 'SecurityContext', and 'Authentication'. Focus on the ThreadLocal storage mechanism of the SecurityContextHolder and the purpose of the three main parts of the Authentication object: principal, credentials, and authorities.
Test your understanding!
Given that the SecurityContextHolder uses a ThreadLocal by default, what potential problem could arise if you spawn a new, unmanaged thread from within a secured method (e.g., using new Thread(() -> { ... }).start();) and try to access security information from that new thread?
Show answer
The SecurityContext would not be propagated to the new thread. Since the SecurityContextHolder stores its context in a ThreadLocal, the information is only available on the original request-processing thread. The new thread would have an empty SecurityContext, and calls to SecurityContextHolder.getContext().getAuthentication() would likely return null. This means any security checks or attempts to retrieve the current user's identity within that new thread would fail.
This is why for asynchronous processing, it's crucial to use Spring-managed mechanisms like @Async, which can be configured to propagate the security context correctly.
Conclusion
In this lesson, we've unpacked the core architecture of Spring Security. You've learned how it uses a sophisticated, interception-based filter model to apply security concerns to web requests. This is a topic that frequently appears in interviews for senior roles, and being able to articulate it clearly demonstrates a deep understanding of the framework.
Key Takeaways:
- Spring Security is fundamentally built on the standard Servlet
Filtermechanism. - The
DelegatingFilterProxyacts as a bridge, connecting the servlet container's lifecycle to the SpringApplicationContext. - The
FilterChainProxyis the main Spring Security bean that manages one or moreSecurityFilterChains. - A
SecurityFilterChainis an ordered list of filters, each performing a specific security task (authentication, authorization, CSRF protection, etc.). - After successful authentication, the user's details are stored in an
Authenticationobject within theSecurityContext. - The
SecurityContextHolderprovides application-wide access to theSecurityContextby storing it in aThreadLocalfor the duration of the request.
Preview of the Next Lesson:
We've seen the architectural "slots" where authentication happens. But how do we tell Spring Security to check usernames and passwords against our own database? In the next lesson, we will implement authentication against a database by creating a custom UserDetailsService. This will be our first step in customizing the default behavior to fit a real-world application.