Unravel › Java concepts › Security
Spring Security basics
Spring Security puts a chain of filters in front of your application.
Learn these first
At a glance
A building with a front desk and keycards.
- 1Every request passes through a SecurityFilterChainYou configure it with HttpSecurity: which paths are public, which need a login, how login works (form, HTTP basic, JWT bearer token).
- 2After a successful login the identity is stored in the SecurityContext, available through SecurityContextHolder or as a controller parameter with @AuthenticationPrincipalIt is held per thread for the duration of the request.
- 3Method-level rules such as @PreAuthorize("hasRole('ADMIN')") protect individual service methods; they work through proxies and need @EnableMethodSecurity
- 4Passwords must never be stored or compared as plain textA PasswordEncoder (typically BCryptPasswordEncoder) hashes on registration and verifies on login.
- Rules are matched top to bottom and the first match wins, so a broad anyRequest().permitAll() placed early silently opens everything below it
- CSRF protection is on by default for browser sessions and rightly so; disable it only for stateless APIs that use tokens in headers, and understand why before you do
- The filters are registered as one FilterChainProxy in the servlet container
@BeanSecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests(a -> a .requestMatchers("/health", "/public/**").permitAll() .requestMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated()) .httpBasic(Customizer.withDefaults()); return http.build();}- line 2 uses SecurityFilterChain, the core of Spring Security basics
Read the full explanation (about 2 min)
Spring Security puts a chain of filters in front of your application. They work out who the caller is (authentication) and whether they may do what they ask (authorization), before a controller is reached.
A mental model
A building with a front desk and keycards. The desk checks who you are and hands you a card; every door then checks whether your card opens it. The rooms never have to ask for ID themselves.
How it works
Every request passes through a SecurityFilterChain. You configure it with HttpSecurity: which paths are public, which need a login, how login works (form, HTTP basic, JWT bearer token).
After a successful login the identity is stored in the SecurityContext, available through SecurityContextHolder or as a controller parameter with @AuthenticationPrincipal. It is held per thread for the duration of the request.
Method-level rules such as @PreAuthorize("hasRole('ADMIN')") protect individual service methods; they work through proxies and need @EnableMethodSecurity.
Passwords must never be stored or compared as plain text. A PasswordEncoder (typically BCryptPasswordEncoder) hashes on registration and verifies on login.
Going deeper
Rules are matched top to bottom and the first match wins, so a broad anyRequest().permitAll() placed early silently opens everything below it. Put specific rules first and end with anyRequest().authenticated().
CSRF protection is on by default for browser sessions and rightly so; disable it only for stateless APIs that use tokens in headers, and understand why before you do.
Authentication proves identity; authorization checks permission on each object. Checking only the role ("is a user") and not ownership ("is this order theirs?") is the classic access-control bug.
The security context is thread-bound. Work handed to another thread (an @Async method, an executor) does not see the logged-in user unless you propagate the context.
Under the hood
The filters are registered as one FilterChainProxy in the servlet container. Each filter handles a concern (session lookup, token parsing, CSRF, exception translation, authorization). Authorization decisions are made by an AuthorizationManager that compares the Authentication with the rule for the request or method.
Common mistakes
- Putting a permissive rule before restrictive ones.
- Storing passwords unhashed or with a fast hash.
- Checking roles but not ownership of the resource.
- Disabling CSRF without understanding the consequence.
- Expecting the logged-in user inside a new thread.
How Unravel recognises it
When you paste code, Unravel looks for these signs of spring security basics. Spotting them yourself is a good habit when you read unfamiliar code:
- Annotations:
@EnableWebSecurity@EnableMethodSecurity@PreAuthorize@PostAuthorize@Secured@RolesAllowed@AuthenticationPrincipal - Types:
SecurityFilterChainHttpSecurityPasswordEncoderBCryptPasswordEncoderUserDetailsServiceAuthenticationManagerSecurityContextHolderOncePerRequestFilterAuthentication
Part of a learning path
- How a Spring request really works · previous: Bean validation (@Valid) · next: @Transactional
- Security for backend developers · next: Spring Security filter chain and authorization rules
Related concepts
Builds on this
Frequently asked questions
What is Spring Security basics?
Spring Security puts a chain of filters in front of your application. They work out who the caller is (authentication) and whether they may do what they ask (authorization), before a controller is reached.
What are the most common mistakes with Spring Security basics?
Putting a permissive rule before restrictive ones. Storing passwords unhashed or with a fast hash. Checking roles but not ownership of the resource. Disabling CSRF without understanding the consequence. Expecting the logged-in user inside a new thread.
How can I see Spring Security basics in real code?
Paste your own Java into Unravel and it will point out where spring security basics appears, explain how it works at the detail level you choose, and draw the flow of the code around it.