Spring Security is a powerful framework for securing Java applications—but have you ever wondered how it actually works behind the scenes? In this guide, we’ll take a deep dive into Spring Security Architecture, breaking down its core components and exploring how requests flow through a basic Spring MVC application. Instead of relying on Spring Boot’s auto-configuration, we’ll manually set up security from scratch, giving you a clear, hands-on understanding of how everything fits together. By the end, you’ll have a solid grasp of Spring Security’s inner workings.
Example Code
This article is accompanied by the following code example: GitHub Link.
Spring Web Workflow Without Spring Security
Before diving into Spring Security, let’s understand how a typical Spring MVC application processes requests:

In a basic Spring MVC application, the request flow is straightforward:
- Client sends an HTTP request
- The request arrives at the DispatcherServlet (Front Controller)
- DispatcherServlet routes the request to appropriate Controller
- Controller processes the request and returns a view name or data
- View is rendered (or data is serialized to the requested format) and sent back as response
Spring Security’s Impact on Request Flow
When we add Spring Security, the request processing flow changes significantly:

Spring Security introduces a chain of filters that process the request before it reaches the DispatcherServlet. This chain handles:
- Authentication (verifying who you are)
- Authorization (verifying what you’re allowed to do)
- Security context management
- Protection against common attacks
Spring Security Architecture
Spring Security’s filter architecture involves two key components: DelegatingFilterProxy and the springSecurityFilterChain bean. The DelegatingFilterProxy is a standard Servlet Filter that bridges the gap between the Servlet container and Spring’s ApplicationContext. It’s needed because Servlet Filters are managed by the Servlet container, while Spring Security’s filters need to be managed by Spring to leverage its features like dependency injection.
When a request comes in, the DelegatingFilterProxy looks up a Spring bean named “springSecurityFilterChain” (of type FilterChainProxy) in the ApplicationContext. This FilterChainProxy is the actual security filter chain that contains and manages all security-related filters. It’s automatically created when you use @EnableWebSecurity in your configuration.
The flow looks like this:

- HTTP Request arrives with headers, method, URL, and parameters
- DelegatingFilterProxy intercepts the request as a Servlet Filter and looks up the “springSecurityFilterChain” bean from Spring’s ApplicationContext
- DelegatingFilterProxy delegates to FilterChainProxy (the springSecurityFilterChain bean), which receives the request
- FilterChainProxy determines which SecurityFilterChain matches the current request URL using RequestMatcher
- FilterChainProxy delegates to the matching SecurityFilterChain which contains its specific list of security filters
- Security Filters process the request in order:
- ……..
- UsernamePasswordAuthenticationFilter (handles login)
- BasicAuthenticationFilter (handles basic auth)
- ……..
- If all filters pass, the request continues to the DispatcherServlet ; if any filter fails, the chain is interrupted
This represents the complete journey of a request through Spring Security’s filter architecture, from initial interception to final security processing.
Project Setup (Manual Configuration)
Spring Boot configuration is on the next section!
In this Section, we’ll configure Spring Security without Spring Boot, handling all configurations manually for better understanding of the framework internals.
Maven Project Setup
- Create a maven project using the web archetype
- Add Spring Security dependencies to
pom.xml
:
<properties>
<spring.version>6.2.3</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
Spring MVC Configuration
- Create base configuration class:
@Configuration
@EnableWebMvc
@ComponentScan("com")
public class AppConfig {
}
This configuration class alongside with @ComponentScan("com")
Tells Spring to scan the “com” package and its sub-packages for components (e.g., @Controller
, @Service
, @Repository
).
- Configure DispatcherServlet:
public class DispatcherServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] {AppConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[] {"/"};
}
}
This configuration maps DispatcherServlet to handle all incoming requests (“/”) and loads web-specific configurations from AppConfig.
Note: For detailed information about DispatcherServlet configuration, refer to “The 3 Ways to Configure DispatcherServlet In Spring MVC” article.
Spring Security Configuration
Spring Security is implemented as a chain of filters. Two main components need to be configured:
DelegatingFilterProxy – The entry point filter
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
// Empty class - Spring Security handles the initialization
}
The SecurityInitializer class creates a DelegatingFilterProxy through the following process:
- When the application starts, AbstractSecurityWebApplicationInitializer’s onStartup method is called
- This method creates a DelegatingFilterProxy (passing springSecurityFilterChain as targetBeanName which will be fetched from the applicationContext when request arrive)
- The filter is registered with the ServletContext
Note: To keep this article concise, I covered DelegatingFilterProxy in detail in a separate article. Read it here: Spring Security DelegatingFilterProxy.
FilterChainProxy (springSecurityFilterChain bean)
@Configuration
@EnableWebSecurity(debug = true)
public class SecurityConfig {
// Configuration will be added here
}
The @EnableWebSecurity
annotation automatically creates the springSecurityFilterChain bean (of type FilterChainProxy) which will contain all security filters.
This setup provides the basic structure needed to start working with Spring Security.
Testing the Configuration
Create a test controller with some endpoints to test the security config:
@RestController
@RequestMapping("/api")
public class TestController {
@GetMapping("/test")
public String privateEndpoint() {
return "This endpoint is used for testing purposes";
}
}
When you access the /test endpoint, you’ll be redirected to the default Spring Security login page /login.

Note: If you’re wondering about the source of the username and password, we’ll explore this in our upcoming articles. We’ll cover how to create custom users and test authentication with them.
Project Setup (Spring Boot case)
For Spring Boot applications, the configuration is much simpler. Just add the Spring Boot Security starter dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>your-version-here</version>
</dependency>
This single dependency will automatically configure Spring Security with its default settings. this dependency is what we called a starter it already has al the necessary dependencies alomgside an autoconfiguration class that will setup evrything for u!
Conclusion
Spring Security is built around a flexible filter chain that handles authentication and authorization seamlessly. By understanding how filters interact with each request, you can better customize and troubleshoot your security configuration.
One Response