Form login vs stateless APIs
Pick the right login style for browsers and for machines, and run both in one app.
Open this lesson in the learning hubKey points
- Browser app? Use
formLogin. The session holds your identity; theJSESSIONIDcookie carries it after login. - Machine client? No session. Send a token on every request and keep the server stateless so any instance can serve it.
httpBasicresends user:password (base64, not encrypted) on every call. Acceptable over TLS internally, weak for public APIs.- One app, both styles: two
SecurityFilterChainbeans —/api/**stateless first, the UI chain second. - Always add
logoutfor the session half. Killing the session is what actually logs a browser user out.
Example
@Bean
@Order(1)
SecurityFilterChain api(HttpSecurity http) throws Exception {
return http
.securityMatcher("/api/**")
.csrf(csrf -> csrf.disable())
.sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(a -> a.anyRequest().authenticated())
.httpBasic(Customizer.withDefaults())
.build();
}
@Bean
@Order(2)
SecurityFilterChain web(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(a -> a
.requestMatchers("/", "/css/**", "/js/**", "/login").permitAll()
.anyRequest().authenticated())
.formLogin(form -> form
.loginPage("/login")
.defaultSuccessUrl("/dashboard", true)
.failureUrl("/login?error"))
.logout(out -> out
.logoutSuccessUrl("/")
.deleteCookies("JSESSIONID"))
.build();
}
Cookies and sessions for browsers, tokens and STATELESS for APIs — never mix them on one path.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Spring Security course, and every lesson in it is listed on the Spring Security contents page.