Think of Spring Security as the bouncer at the door of your app: it checks who you are, what you may enter, and blocks everyone else before the controller even sees the request.
Question: What is Spring Security?
Answer: Spring Security is the security framework for Spring and Spring Boot. It handles authentication (proving identity) and authorization (deciding access), and it does that mostly through a chain of servlet filters that runs before your business code. In Spring Boot, adding the security starter protects your app by default, then you customize which endpoints are public, which need a login, and which need roles.
Interview-Ready Answer: Spring Security is the framework I use in Spring Boot to protect requests before they reach my controllers. It authenticates users, authorizes access with roles or permissions, and can also handle login, logout, CSRF protection, and session management. One detail I like is that it works through a filter chain, so the security decision happens early and consistently for every request.
Spring Security is the security layer that sits in front of your web app. On the servlet stack, it is built around filters, which are small request interceptors that can inspect, reject, or enrich a request before it reaches a controller. The current user is stored in a SecurityContext (a holder for the current authentication), and Spring Boot wires sensible defaults when the security starter is present.
DispatcherServlet and your controller.SecurityContextHolder, which uses a ThreadLocal (per-thread storage) so the current request thread can remember the user without passing it through every method.AuthenticationManager and one or more AuthenticationProvider implementations to verify them.Authentication object in the SecurityContext. On failure, it returns 401 Unauthorized or redirects to a login page, depending on the configured entry point.403 Forbidden.| Concept | Meaning | Spring feature | Failure |
|---|---|---|---|
| Authentication | Who are you? | Login, Basic, JWT | 401 |
| Authorization | What can you do? | hasRole, hasAuthority | 403 |
@PreAuthorize.O(1): a small, constant amount of filter work and rule matching.BCryptPasswordEncoder uses a cost factor of 10 by default, and a single password check often takes tens to hundreds of milliseconds depending on hardware and configuration. That slowness is a feature, because logins are rare and brute-force attacks become costly.SecurityContext in the HTTP session. If you use token-based auth, each request carries its own proof, which is common for stateless APIs.WebSecurityConfigurerAdapter; the modern style is to define a SecurityFilterChain bean.permitAll() does not bypass the filter chain; it only says the request is allowed through authorization.web.ignoring() skips the security chain completely, so use it sparingly, usually only for static assets.hasRole("ADMIN") expects the logical role name. Spring adds the ROLE_ prefix when you use roles("ADMIN") in user setup.403 can come from missing permission or from CSRF protection on a state-changing request, so do not assume every 403 is a role problem.Real-World Story: Imagine an e-commerce checkout service deployed to Kubernetes. The team adds Spring Security and forgets that /actuator/health is called by the load balancer without a login. Suddenly the health probe gets 401 Unauthorized responses, pods turn Unready, the autoscaler restarts them, and checkout traffic starts failing with 503 Service Unavailable. Logs show repeated unauthenticated health checks even though the app works locally in a browser because the developer is already logged in.
The bug is not in the controller code; it is in the security rule set. The fix is to explicitly allow the health endpoint or place actuator routes in a separate security configuration. This is exactly why interviewers like Spring Security: a tiny rule can protect your app or take production down if it is wrong.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@Configuration
class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(auth -> auth
.requestMatchers("/public").permitAll()
.requestMatchers("/admin").hasRole("ADMIN")
.anyRequest().authenticated()
);
// Form login gives you the browser login page.
// HTTP Basic makes the demo easy to test with curl or Postman.
http.formLogin(Customizer.withDefaults());
http.httpBasic(Customizer.withDefaults());
return http.build();
}
@Bean
PasswordEncoder passwordEncoder() {
// BCrypt is the safe default: it stores hashes, not plain text.
// Its work factor makes brute-force attacks more expensive.
return new BCryptPasswordEncoder();
}
@Bean
UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
UserDetails alice = User.withUsername("alice")
.password(passwordEncoder.encode("password"))
.roles("USER")
.build();
UserDetails bob = User.withUsername("bob")
.password(passwordEncoder.encode("password"))
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(alice, bob);
}
}
@RestController
class DemoController {
@GetMapping("/public")
public String publicEndpoint() {
return "This endpoint is open to everyone.";
}
@GetMapping("/me")
public String me(Authentication authentication) {
return "You are " + authentication.getName()
+ " with authorities " + authentication.getAuthorities();
}
@GetMapping("/admin")
public String admin(Authentication authentication) {
// alice can reach /me, but gets 403 Forbidden here because she is not an admin.
return "Welcome, " + authentication.getName() + ". You are an admin.";
}
}
Follow-up & Tricky Questions:
Authentication, and access rules like hasRole decide whether the request may continue.SecurityFilterChain? It is the bean that defines how Spring Security filters and authorizes requests. In Spring Security 6+, it is the standard replacement for the old adapter-based configuration style.SecurityContext? It is the container for the current Authentication. Spring stores it in SecurityContextHolder so controllers and services can ask who the current user is.PasswordEncoder? Because plain-text passwords are unsafe. A PasswordEncoder hashes passwords and verifies them safely, and BCrypt is the common default choice.401 or a login page; if the user is logged in but lacks permission, it returns 403.permitAll() remove security? No. It only allows authorization to pass for that route; the request still goes through the security filter chain.hasRole("ADMIN") check for ADMIN or ROLE_ADMIN? It checks the logical role name ADMIN, while Spring typically stores it as ROLE_ADMIN under the hood when you use roles("ADMIN").Common gotcha questions:
Common Mistakes:
401 with 403. Correction: 401 means not authenticated, while 403 means authenticated but not allowed.PasswordEncoder, with BCrypt as the common default.WebSecurityConfigurerAdapter. Correction: in Spring Security 6, define a SecurityFilterChain bean instead.Memory Hook: Spring Security is the club door: authentication checks your ID, authorization checks your wristband.
Cheat Sheet:
SecurityContext.Practice Tasks:
/user endpoint and allow both USER and ADMIN roles to call it.UserDetailsService and keep the same access rules.POST endpoint and observe how CSRF behaves, then learn when it should be kept on or disabled.