How Spring Security Protects Your Application
Spring Security works by wrapping your entire application in a chain of servlet filters that run before any request reaches your @RestController methods. Each filter has one job — checking a header, validating a session, or rejecting an unauthenticated request — and if every filter passes, the request is finally handed to your controller. This means authentication and authorization are handled uniformly, outside your business logic, so you rarely need to write manual 'if (user == null)' checks inside controller methods.
Cricket analogy: It's like the layers of dismissal appeals in a match — the umpire, then the third umpire on review, then DRS with ball-tracking — each check must clear the batter before play (the request) is allowed to continue to the next over.
The Security Filter Chain
At the heart of Spring Security is the SecurityFilterChain bean, which Spring Boot auto-configures and registers through a single DelegatingFilterProxy in the servlet container. Inside it, filters run in a strict, well-known order: UsernamePasswordAuthenticationFilter processes form logins, BasicAuthenticationFilter handles HTTP Basic headers, ExceptionTranslationFilter catches AuthenticationException and AccessDeniedException, and FilterSecurityInterceptor makes the final authorization decision by consulting the configured access rules. Understanding this order matters because a custom filter added in the wrong position — for example, before the authentication filter instead of after — will never see an authenticated user.
Cricket analogy: It's like a bowling attack's fixed order — the new-ball pacer opens, the first-change bowler follows, and the spinner comes on later — swap Bumrah's opening spell with a part-timer's and the tactical plan falls apart.
Configuring HTTP Security Rules
You configure Spring Security declaratively by defining a SecurityFilterChain bean and calling methods on the HttpSecurity builder, such as authorizeHttpRequests to state which URL patterns require which roles, permitAll to open specific paths like /login or /public, and anyRequest().authenticated() as a catch-all default-deny rule. You also configure cross-cutting concerns here, like disabling CSRF protection for stateless REST APIs that use tokens instead of cookies, or enabling formLogin() and httpBasic() to choose which authentication mechanisms are active. The order rules are declared in matters too — Spring Security evaluates authorizeHttpRequests matchers top-to-bottom and uses the first one that matches.
Cricket analogy: It's like a fielding captain setting a field plan — third slip and gully for the new ball, then switching to a leg-side trap for a set batter — each configuration targets a specific matchup, evaluated in the order it's set.
Password Encoding and Authentication Providers
When a user submits credentials, an AuthenticationProvider — typically DaoAuthenticationProvider — loads the stored user via a UserDetailsService and compares the submitted password against the stored hash using a PasswordEncoder, most commonly BCryptPasswordEncoder. BCrypt is deliberately slow and includes a per-password salt, which makes brute-force and rainbow-table attacks impractical even if the database leaks. Storing plaintext or even fast-hashed (MD5, SHA-1) passwords is a serious security failure, because a leaked database instantly exposes every user's real password; BCrypt's adjustable work factor lets you keep pace with hardware improvements over time.
Cricket analogy: It's like comparing a bowler's action against a biomechanics report frame-by-frame rather than just trusting a scorecard — BCrypt does deliberate, careful verification work instead of a quick, exploitable glance.
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public/**", "/login").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults())
.formLogin(Customizer.withDefaults());
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}If you add spring-boot-starter-security to your dependencies without defining a SecurityFilterChain bean, Spring Boot auto-generates a default configuration that locks down every endpoint and prints a random one-time password to the console at startup. This is fine for a quick demo, but never rely on it in a real project — always define an explicit SecurityFilterChain with a real UserDetailsService and PasswordEncoder before deploying anywhere.
- Spring Security intercepts requests through a chain of servlet filters before they reach controllers.
- The SecurityFilterChain bean defines which filters run and in what order.
- authorizeHttpRequests rules are evaluated top-to-bottom; the first matching rule wins.
- DaoAuthenticationProvider verifies credentials via a UserDetailsService and a PasswordEncoder.
- BCryptPasswordEncoder is the standard choice: it is slow by design and salts each hash.
- Never store plaintext or fast-hashed passwords in production databases.
- Without an explicit SecurityFilterChain, Spring Boot's auto-configuration locks down all endpoints by default.
Practice what you learned
1. What is the primary role of the SecurityFilterChain bean in a Spring Boot application?
2. Why is BCryptPasswordEncoder preferred over a fast hash like plain SHA-256 for storing passwords?
3. In authorizeHttpRequests, how are multiple matcher rules evaluated?
4. What happens if spring-boot-starter-security is added with no custom SecurityFilterChain bean?
5. Which component loads user details and delegates password comparison during authentication?
Was this page helpful?
You May Also Like
Authentication and Authorization in Spring
How Spring Security distinguishes proving identity (authentication) from granting access (authorization), covering roles, method security, and JWT-based stateless auth.
Application Properties and Profiles
How Spring Boot externalizes configuration through application.properties/yml, property precedence, and environment-specific profiles.
Spring Boot Actuator
How Spring Boot Actuator exposes production-ready monitoring endpoints for health checks, metrics, and application internals.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics
Web DevelopmentNext.js Study Notes
JavaScript · 30 topics