Introduction to Spring Security
Introduction to Spring Security
Every web application eventually faces the same question: who is allowed in, and what are they allowed to do? Spring Security is the standard answer for the Spring ecosystem. It is a powerful, highly customisable framework that handles authentication (proving who you are) and authorisation (deciding what you may access), while also providing defences against a catalogue of common web-layer attacks.
This lesson covers what Spring Security actually protects against, the mental model you need before writing any configuration, and exactly how the library integrates with a Spring Boot 3 application without any extra plumbing code.
What Threats Does Spring Security Address?
Before configuring anything it is worth being concrete about the attacks Spring Security guards you from by default.
- Cross-Site Request Forgery (CSRF): A malicious page tricks a user's browser into firing a state-changing request (e.g. a bank transfer) to your application, riding the user's session cookie. Spring Security enables CSRF token protection automatically for every state-changing HTTP method (
POST,PUT,DELETE,PATCH). - Session fixation: An attacker forces a known session ID onto a victim before login. Spring Security migrates (or invalidates) the session on every successful authentication, making pre-issued session IDs useless.
- Clickjacking: Embedding your site in a hidden iframe lets an attacker overlay fake UI on top. Spring Security emits an
X-Frame-Options: DENYheader by default. - Content sniffing & XSS vectors: Headers such as
X-Content-Type-Optionsand theContent-Security-Policysupport built intoHeadersConfigurermitigate browser-level attacks. - Credential brute-forcing: By enforcing authentication on every sensitive route and plugging into password-encoding strategies, Spring Security eliminates the easy wins for automated credential-stuffing attacks.
The Core Concepts at a Glance
Spring Security is built around three abstractions that repeat throughout every feature you will learn:
- Principal — the currently authenticated entity (a user, a service account, an OAuth2 client). Stored in a thread-local
SecurityContext. - Authentication — an object that represents both the credentials submitted during login and, once verified, the confirmed identity and its authorities. The interface is
org.springframework.security.core.Authentication. - GrantedAuthority — a permission or role attached to the authenticated principal (e.g.
ROLE_ADMIN,orders:read).
These three objects flow through every request and are what your authorisation rules ultimately interrogate.
How Spring Security Plugs into a Spring Boot App
Spring Security integrates at the Servlet filter layer. It registers a single entry-point filter — DelegatingFilterProxy — with the servlet container, which in turn delegates to a Spring-managed FilterChainProxy. That proxy holds an ordered list of security filter chains, each of which is a sequence of specialised filters (CSRF, session management, authentication, authorisation, and more).
The practical implication: Spring Security operates before any @Controller or @RestController ever runs. A request that fails authentication or authorisation is rejected at the filter level and never reaches your application code.
That single starter dependency is all you need. Spring Boot's auto-configuration detects it on the classpath and:
- Creates a default
UserDetailsServicewith an in-memory user (user/ random password). - Registers the
FilterChainProxywith the servlet container. - Enables HTTP Basic and form-login on every URL.
- Switches on CSRF protection, security headers, and session fixation protection.
--debug and search for SecurityAutoConfiguration in the output. You will see exactly which beans were created and which conditions were matched. This is invaluable when something does not behave as expected.
A Minimal Verified Example
Let us write the smallest possible Spring Boot 3 application that demonstrates Spring Security in action. Nothing is configured — we rely entirely on auto-configuration.
Start the application. In the console you will see a line similar to:
A GET /hello request without credentials receives a 401 Unauthorized response with a WWW-Authenticate: Basic header. Supply the username user and the generated password via HTTP Basic and the request succeeds. Spring Security intercepted the request, verified the credentials, stored the resulting Authentication in the SecurityContext, and then allowed the request to continue to the controller.
The SecurityContext and the Current User
Once a request is authenticated, the verified Authentication object lives in a thread-local SecurityContextHolder. Any code running on that thread — including your controllers and services — can read it:
In practice you will inject the authentication as a method parameter using @AuthenticationPrincipal or via Spring MVC's parameter injection, which is cleaner and more testable. But the raw SecurityContextHolder call makes the underlying model explicit.
SecurityContextHolder strategy (MODE_THREADLOCAL) does not propagate the context to child threads or async tasks. If you use @Async, CompletableFuture, or virtual threads, switch to MODE_INHERITABLETHREADLOCAL or use Spring Security's DelegatingSecurityContextExecutor wrapper — otherwise the security context will be null on the worker thread and your authorisation checks will silently fail.
Where This Tutorial Goes from Here
With the big picture in place, the remaining lessons build on it systematically. Lesson 2 dissects the Security Filter Chain so you understand what fires on every request. Lesson 3 draws the precise line between authentication and authorisation. Lesson 4 shows how to replace auto-configuration with a custom SecurityFilterChain bean — the idiomatic approach in Spring Security 6. Lessons 5 and 6 cover loading users and encoding passwords. The final lessons tackle authorisation rules, method-level security, and assembling a complete secured web application.
Summary
Spring Security integrates at the servlet filter layer, running before any controller code. Adding the spring-boot-starter-security dependency activates a closed-by-default security posture that protects against CSRF, session fixation, clickjacking, and content-sniffing attacks out of the box. The three core abstractions — Principal, Authentication, and GrantedAuthority — flow through every request and underpin every feature you will configure in the lessons ahead. The verified Authentication is stored in a thread-local SecurityContextHolder and is accessible to all code on the request thread.