Spring Security Basics
Spring Security protects your application with a chain of filters that first authenticate who a user is and then authorize what they may do — with safely hashed passwords at the core.
Learn Spring Security Basics in our free Java course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Java course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
You should understand dependency injection and how Spring beans are wired, plus the basics of building a Spring Boot app and its profiles . Familiarity with HTTP requests and roles helps.
💡 Analogy: Picture a private club. At the door, a doorman checks your ID — that is authentication : proving you are who you claim to be. Inside, a guest list says which rooms each member may enter — that is authorization . Spring Security is the whole security desk: a line of staff (the filter chain ) where the first checks your ID, the next checks the guest list, and only then are you let through to the party (your controller). And crucially, the club never writes your real password on the list — it keeps a scrambled, un-reversible BCrypt version.
Two different questions, two different jobs: "who are you?" then "what may you do?".
These two are constantly confused. Authentication verifies identity (login). Authorization grants or denies access based on that identity's roles/authorities. We can model both in plain Java to make the distinction concrete.
Spring's BCryptPasswordEncoder is the recommended choice: it produces a salted , adaptive , one-way hash. We can't run BCrypt without Spring on the classpath, but the demo below shows the universal principle — a salt makes equal passwords hash differently, and the original is never stored.
In Spring Security 6 you configure security by registering a SecurityFilterChain bean (the old WebSecurityConfigurerAdapter is gone). You declare which paths are public, which need a role, and that everything else needs authentication.
Answer: "What may you do?" — it grants or denies access for an already-identified user, based on roles/authorities.
Answer: a SecurityFilterChain bean defined in a @Configuration class with @EnableWebSecurity .
Answer: each hash uses a unique random salt , so identical passwords map to different stored values.
🎯 YOUR TURN — Role-Based Access
Write canAccess(userRoles, requiredRole) and check two endpoints against Bob's roles.
🧩 MINI-CHALLENGE — A Tiny Filter Chain
Walk an ordered list of path rules and apply the first match to decide ALLOW / DENY / NEEDS LOGIN.
You can now distinguish authentication from authorization, configure a SecurityFilterChain bean in Spring Security 6, secure endpoints by path and role, store passwords safely with BCrypt, and stand up in-memory users for testing.
Next up: JWT Authentication — stateless, token-based security with signed Bearer tokens.
Practice quiz
In Spring Security 6, how do you configure HTTP request rules?
- By defining a SecurityFilterChain bean
- By extending WebSecurityConfigurerAdapter
- By editing web.xml
- By annotating main() with @Secure
Answer: By defining a SecurityFilterChain bean. WebSecurityConfigurerAdapter was removed; you now register a SecurityFilterChain bean using a component-based, lambda DSL configuration.
What does authentication establish?
- What a user is allowed to do
- Who the user is
- How fast the request is
- Which database to use
Answer: Who the user is. Authentication answers 'who are you?' by verifying credentials; authorization is the separate question of what you may do.
What does authorization decide?
- The password hash algorithm
- The user's identity
- Whether an authenticated user may access a resource
- The server's port
Answer: Whether an authenticated user may access a resource. Authorization governs access: given a known identity, may this principal perform this action or reach this endpoint?
Which PasswordEncoder is the recommended default for hashing passwords?
- NoOpPasswordEncoder
- Base64Encoder
- MD5PasswordEncoder
- BCryptPasswordEncoder
Answer: BCryptPasswordEncoder. BCryptPasswordEncoder applies an adaptive, salted one-way hash; NoOp stores plaintext and MD5 is broken for passwords.
Why is BCrypt 'adaptive'?
- It changes the password automatically
- Its work factor (strength) can be increased as hardware speeds up
- It compresses the hash
- It caches results
Answer: Its work factor (strength) can be increased as hardware speeds up. BCrypt has a configurable cost/strength parameter, so you can raise it over time to keep brute-forcing expensive.
Which interface supplies user details (username, password, authorities) during authentication?
- UserDetailsService
- JdbcTemplate
- RestController
- EntityManager
Answer: UserDetailsService. UserDetailsService.loadUserByUsername returns a UserDetails the AuthenticationManager checks against the supplied credentials.
In the SecurityFilterChain DSL, which call requires authentication on every request?
- permitAll()
- denyAll()
- anyRequest().authenticated()
- ignore()
Answer: anyRequest().authenticated(). authorizeHttpRequests(a -> a.anyRequest().authenticated()) means every unmatched request needs an authenticated principal.
What is InMemoryUserDetailsManager useful for?
- Defining a small fixed set of users in memory for demos/tests
- Production user storage at scale
- Encrypting the database
- Serving static files
Answer: Defining a small fixed set of users in memory for demos/tests. It holds UserDetails in memory — handy for examples, tests, and prototypes, but not a real persistent user store.
Spring Security is built primarily as...
- a single servlet
- a chain of servlet Filters
- a JSON parser
- a thread pool
Answer: a chain of servlet Filters. Security is applied via a filter chain; each filter handles one concern (e.g. authentication) before the request reaches your controller.
Where is the authenticated principal stored for the current request?
- In a public static field
- In the URL
- In the SecurityContext (held in SecurityContextHolder)
- In application.properties
Answer: In the SecurityContext (held in SecurityContextHolder). After authentication, the Authentication is placed in the SecurityContext, accessible thread-locally via SecurityContextHolder.