Spring Security In Action Second Edition Page
With sessions disabled, every request must carry its own proof of identity. Here is a simplified implementation of a JWT service as described in the book:
"The best session is no session at all." — A mantra for modern Spring Security developers. spring security in action second edition
The most critical piece from the second edition is the custom filter. It intercepts every request, grabs the Authorization: Bearer header, and populates the SecurityContextHolder for that request only (because there is no session to carry it forward). With sessions disabled, every request must carry its
public String extractUsername(String token) return Jwts.parserBuilder() .setSigningKey(key) .build() .parseClaimsJws(token) .getBody() .getSubject(); It intercepts every request, grabs the Authorization: Bearer
@Configuration @EnableWebSecurity public class StatelessSecurityConfig @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception http .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.STATELESS) ) .authorizeHttpRequests(auth -> auth .requestMatchers("/login", "/refresh").permitAll() .anyRequest().authenticated() ); // No formLogin() - we use a custom filter return http.build();
To go stateless, we need to disable session creation entirely:
@Component public class JwtService private final SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256); private final long EXPIRATION = 86400000; // 24 hours public String generateToken(String username) return Jwts.builder() .setSubject(username) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION)) .signWith(key) .compact();