Spring Security Basics
Spring Security provides authentication, authorization, and protection against common attacks (CSRF, XSS, etc.). This article explains core concepts, common configuration, and a reference table to get you started.
Overview
- Authentication: Answers "who are you?" Common methods: form login, JWT, OAuth2, Basic Auth.
UserDetailsServiceloads user data;PasswordEncodervalidates passwords. - Authorization: Answers "what can you do?" Role-based (ROLE_ADMIN), permission-based (user:read), method-level
@PreAuthorize, and URL rules. - Filter chain: Each request passes through a series of filters (e.g.
UsernamePasswordAuthenticationFilter,FilterSecurityInterceptor). After auth succeeds, authorization decides whether to allow the request. - Session: Default is session-based; you can switch to stateless JWT where each request carries a token.
Example
Example 1: Basic security config
Java@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests(a -> a .requestMatchers("/public/**").permitAll() .requestMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated() ).formLogin(); return http.build(); } }
permitAll(): no auth required.hasRole("ADMIN"): requires ROLE_ADMIN.authenticated(): any logged-in user.- Order matters: more specific rules first;
anyRequest()should come last.
Example 2: Custom UserDetailsService
Java@Service public class MyUserDetailsService implements UserDetailsService { @Autowired private UserRepository userRepo; @Override public UserDetails loadUserByUsername(String username) { User user = userRepo.findByUsername(username) .orElseThrow(() -> new UsernameNotFoundException(username)); return new org.springframework.security.core.userdetails.User( user.getUsername(), user.getEncodedPassword(), user.getAuthorities() ); } }
- Spring Security uses
UserDetailsfor the authenticated principal. Your service loads from DB and returns aUser(or custom implementation) with username, password, and authorities.
Example 3: PasswordEncoder
Java@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } // When saving a new user: String encoded = passwordEncoder.encode(rawPassword); // Validation is done by Spring; you only need to return the encoded password from UserDetails
- Never store plain text passwords. BCrypt, Argon2, SCrypt are recommended. Spring compares the raw password from the login form with the encoded one from
UserDetails.
Example 4: JWT flow
- On login success, generate a JWT and return it (e.g. in response body or cookie).
- Subsequent requests send
Authorization: Bearer <token>. - A
JwtAuthenticationFilter(or similar) parses the token, validates it, and setsSecurityContext. - No server-side session; the token carries identity and optionally roles.
Example 5: Core components
| Component | Role |
|---|---|
| UserDetailsService | Load user by username; return UserDetails |
| PasswordEncoder | Encode and validate passwords |
| AuthenticationManager | Entry point for authentication |
| SecurityContext | Holds current Authentication (ThreadLocal) |
| FilterSecurityInterceptor | Decides if request is allowed (authorization) |
Example 6: Method-level authorization
Java@PreAuthorize("hasRole('ADMIN') or #id == authentication.principal.id") public User getById(Long id) { } @PreAuthorize("hasAuthority('user:read')") public List<User> list() { }
@PreAuthorizeuses SpEL;#idis the method parameter;authentication.principalis the current user.- Enable with
@EnableMethodSecurity(or@EnableGlobalMethodSecurity(prePostEnabled = true)in older versions).
Example 7: CSRF
- For stateful apps (form login, cookies), CSRF protection is on by default. Include the CSRF token in forms.
- For stateless APIs (JWT in header), CSRF is usually disabled:
http.csrf(csrf -> csrf.disable()). - CSRF attacks abuse the browser's automatic sending of cookies; with JWT in a header, the attacker cannot add it from another site.
Core Mechanism / Behavior
- Filter chain: Filters run in order.
UsernamePasswordAuthenticationFilterhandles form login;FilterSecurityInterceptorenforces URL authorization. Custom filters can be added. - SecurityContext: Stored in
ThreadLocal; cleared after the request. Holds the currentAuthentication(principal, credentials, authorities). - PasswordEncoder: One-way hash; verification compares hash of input with stored hash. Use adaptive algorithms (BCrypt, Argon2) that are slow by design.
Key Rules
- Passwords: Always hash with
PasswordEncoder; never store plain text. - CSRF: Stateful forms need CSRF token; for pure API + JWT you can disable it.
- Least privilege: Default deny; explicitly permit what is needed. Be careful with
permitAllin production. - Sensitive endpoints: Protect admin and internal APIs; avoid exposing them without auth.
What's Next
See API Gateway for centralized auth. See OAuth2 and JWT for auth protocols.