How to Set Up Spring Security in Spring Boot 3.x
Add one dependency and everything's locked. The real setup is deciding what to unlock, and why.
The thing that surprises people coming to Spring Security is how little you have to do to start. Add the spring-boot-starter-security dependency, restart the application, and the whole thing is locked. Every endpoint now demands a login. Spring Boot quietly creates a user named "user," prints a random password to the startup logs, and that's your entire app secured before you've written a single line of security code.
That default matters more than it looks. The starting posture is deny everything — which is exactly the right default for security. You want a system where access is granted deliberately, not something you have to remember to take away. Locked-by-default means a forgotten endpoint is safe, not exposed.
Then you replace the defaults with intent
The auto-configuration is a starting point, not a destination. The real setup is telling Spring Security what your actual rules are: which URLs are public, which require a login, and how people authenticate. In Spring Boot 3.x, running on Spring Security 6, you do that by defining a SecurityFilterChain bean.
This is the exact spot where older tutorials lead you wrong. If a guide has you extend WebSecurityConfigurerAdapter, stop — that class was removed in Spring Security 6. The modern approach is a method annotated with @Bean that takes an HttpSecurity object, configures it, and returns the built filter chain. If you learned Spring Security a few years ago, this is the single change that makes everything else look unfamiliar.
The Lambda DSL reads the way the old style should have
The configuration uses what's called the Lambda DSL. Instead of chaining calls together and stitching them with .and(), you pass a small lambda to configure each concern — one for which requests need authorization, one for how login works, and so on. It's marginally more verbose to look at and considerably clearer to read, because each block is visibly self-contained. Inside the authorization block you spell the rules out plainly: these paths permitAll, everything else authenticated. Read top to bottom, it says exactly what it does.
What the defaults handed you for free
It's worth knowing what you inherited without asking, because some of it you'll be tempted to switch off. Out of the box you get CSRF protection, sensible session handling, an expectation that passwords are hashed rather than stored raw, and a set of secure HTTP headers. These are on for good reasons. You can disable any of them, and there are legitimate cases for it — a stateless token API turns off CSRF and server-side sessions deliberately — but "I turned it off because the tutorial did" is not one of those cases.
Where people shoot themselves in the foot
The common failures are all the same shape: opening too much. A permitAll that's broader than intended. A CSRF disable copied without understanding why. A matcher ordered so a permissive rule shadows a stricter one that should have caught the request first. Order matters in the chain — the first rule that matches wins — and it's easy to write rules that quietly never fire.
Setting up Spring Security isn't really about getting it to turn on; it turns on the moment the dependency lands. The work is the opposite of what beginners expect: not adding security, but carefully deciding what to open — and being able to say why for each thing you unlocked.






