In un’applicazione reale è raro usare la pagina di login generata automaticamente da Spring Security. Quella pagina è molto utile per testare rapidamente la configurazione, ma in un progetto professionale quasi sempre serve una maschera di login personalizzata, coerente con il design della web application.
Una maschera di login personalizzata in Spring Security permette di controllare HTML, CSS, messaggi di errore, layout, branding, comportamento dopo il login, gestione del logout e protezione CSRF.
Spring Security offre un meccanismo molto flessibile per personalizzare il form login. Possiamo indicare una pagina di login custom, configurare l’URL a cui inviare username e password, definire la pagina di destinazione dopo l’autenticazione, gestire errori di login e impostare il logout.
In breve: per creare un login personalizzato in Spring Security bisogna configurare
formLogin(), permettere l’accesso pubblico alla pagina di login e alle risorse statiche, inviare il form con metodoPOSTa/logine includere il token CSRF.
Indice dei contenuti
- Cos’è una maschera di login personalizzata
- Come funziona il form login in Spring Security
- Struttura del progetto
- Dipendenze Maven
- Configurazione moderna con SecurityFilterChain
- Configurare una pagina di login custom
- HTML della pagina di login
- Token CSRF nel form di login
- Gestione degli errori di autenticazione
- Parametri username e password
- Configurazione del logout
- Homepage protetta dopo il login
- Esempio con Thymeleaf
- Esempio legacy con JSP
- Configurazione XML legacy
- WebSecurityConfigurerAdapter e migrazione
- Errori comuni
- Best practice
- FAQ sul login personalizzato in Spring Security
Cos’è una maschera di login personalizzata
Una maschera di login personalizzata è una pagina creata dallo sviluppatore per raccogliere le credenziali dell’utente e inviarle a Spring Security per l’autenticazione.
La pagina può essere realizzata con:
- Thymeleaf;
- JSP;
- HTML statico servito dall’applicazione;
- template engine alternativi;
- frontend separato, per esempio React, Angular o Vue;
- una pagina generata dal backend Spring MVC.
Il punto importante è che il form deve rispettare alcune regole attese da Spring Security. In particolare, deve inviare una richiesta POST all’URL configurato per il login, includere i parametri delle credenziali e, se la protezione CSRF è attiva, includere anche il token CSRF.
Login generato automaticamente vs login personalizzato
| Tipo di login | Vantaggi | Limiti |
|---|---|---|
| Login generato da Spring Security | Subito disponibile, utile per test e prototipi. | Design generico, poco adatto a progetti reali. |
| Login personalizzato | Controllo completo su HTML, CSS, messaggi e UX. | Richiede configurazione corretta di URL, CSRF e permessi. |
Come funziona il form login in Spring Security
Il form login di Spring Security si basa su un flusso abbastanza semplice:
Utente apre una pagina protetta
↓
Spring Security intercetta la richiesta
↓
L’utente viene reindirizzato alla pagina di login
↓
L’utente invia username e password
↓
Spring Security autentica le credenziali
↓
Login corretto → redirect alla pagina protetta
Login fallito → redirect alla pagina di login con errore
Il form di login non deve autenticare direttamente l’utente nel codice HTML. Deve semplicemente inviare le credenziali all’endpoint gestito da Spring Security.
Per impostazione comune, Spring Security si aspetta:
- una richiesta
POSTverso/login; - un parametro
username; - un parametro
password; - un token CSRF se la protezione è attiva;
- eventuale parametro
errorper mostrare un messaggio di login fallito; - eventuale parametro
logoutper mostrare un messaggio di logout completato.
Concetto chiave: il form personalizzato è tuo, ma l’elaborazione dell’autenticazione resta gestita da Spring Security.
Struttura del progetto
Una struttura semplice per un progetto Spring Boot con login personalizzato può essere questa:
src
└── main
├── java
│ └── it.javaboss.security
│ ├── SecurityConfig.java
│ ├── HomeController.java
│ └── UserController.java
└── resources
├── templates
│ ├── login.html
│ └── index.html
├── static
│ ├── css
│ │ └── style.css
│ └── images
└── application.properties
In questo esempio:
SecurityConfig.javacontiene la configurazione di Spring Security;login.htmlcontiene la pagina di login;index.htmlè una pagina protetta;static/css/style.csscontiene il CSS della maschera;- le risorse statiche devono essere accessibili anche agli utenti non autenticati.
Dipendenze Maven
In un progetto Spring Boot moderno, le dipendenze principali sono:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
</dependency>
Se usi JSP, la configurazione cambia e può richiedere dipendenze e setup specifici per il servlet container. Per i nuovi progetti Spring Boot, Thymeleaf è spesso più semplice e naturale.
Configurazione moderna con SecurityFilterChain
Nelle versioni moderne di Spring Security si usa un bean SecurityFilterChain per configurare la sicurezza HTTP.
Un esempio base di configurazione per login personalizzato è il seguente:
package it.javaboss.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/login", "/css/**", "/images/**", "/js/**").permitAll()
.anyRequest().authenticated()
)
.formLogin(form -> form
.loginPage("/login")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/", true)
.failureUrl("/login?error=true")
.permitAll()
)
.logout(logout -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout=true")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID")
.permitAll()
);
return http.build();
}
}
Questa configurazione fa diverse cose:
- permette a tutti di accedere alla pagina
/login; - permette a tutti di scaricare CSS, JavaScript e immagini;
- richiede autenticazione per tutte le altre richieste;
- imposta una pagina di login personalizzata;
- configura l’URL che processa il login;
- configura il redirect in caso di login corretto;
- configura il redirect in caso di errore;
- configura il logout.
Nota moderna: nelle versioni attuali di Spring Security non è più consigliato basarsi su
WebSecurityConfigurerAdapter. È preferibile dichiarare un beanSecurityFilterChain.
Configurare una pagina di login custom
Il punto centrale della configurazione è questo blocco:
.formLogin(form -> form
.loginPage("/login")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/", true)
.failureUrl("/login?error=true")
.permitAll()
)
Vediamo il significato dei metodi principali.
| Metodo | Significato |
|---|---|
loginPage("/login") |
Indica la pagina che mostra il form di login. |
loginProcessingUrl("/login") |
Indica l’URL a cui il form deve inviare username e password. |
defaultSuccessUrl("/", true) |
Indica dove reindirizzare l’utente dopo login corretto. |
failureUrl("/login?error=true") |
Indica dove reindirizzare l’utente in caso di login fallito. |
permitAll() |
Permette a tutti di accedere agli endpoint necessari al login. |
Controller per mostrare la pagina di login
package it.javaboss.security;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class LoginController {
@GetMapping("/login")
public String login() {
return "login";
}
}
Con Thymeleaf, questo metodo cerca il template:
src/main/resources/templates/login.html
HTML della pagina di login
La pagina di login deve contenere un form che invia una richiesta POST all’URL configurato con loginProcessingUrl.
Template login.html con Thymeleaf
<!DOCTYPE html>
<html lang="it" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Login</title>
<link rel="stylesheet" th:href="@{/css/style.css}">
</head>
<body>
<main>
<section>
<h1>Login</h1>
<div th:if="${param.error}">
<p>Username o password non validi.</p>
</div>
<div th:if="${param.logout}">
<p>Logout eseguito correttamente.</p>
</div>
<form th:action="@{/login}" method="post">
<div>
<label for="username">Username</label>
<input type="text" id="username" name="username" autocomplete="username" required>
</div>
<div>
<label for="password">Password</label>
<input type="password" id="password" name="password" autocomplete="current-password" required>
</div>
<input type="hidden"
th:name="${_csrf.parameterName}"
th:value="${_csrf.token}">
<button type="submit">Accedi</button>
</form>
</section>
</main>
</body>
</html>
Gli elementi più importanti sono:
method="post";th:action="@{/login}";name="username";name="password";- campo hidden con token CSRF.
Attenzione: se il form non invia i parametri con i nomi attesi, Spring Security non riuscirà a leggere username e password.
Token CSRF nel form di login
Spring Security abilita normalmente la protezione CSRF per le applicazioni web basate su sessione. Questo significa che le richieste modificative, come il login via POST o il logout via POST, devono includere un token valido.
In Thymeleaf possiamo includere il token così:
<input type="hidden"
th:name="${_csrf.parameterName}"
th:value="${_csrf.token}">
In JSP, invece, si può usare una sintassi simile:
<input type="hidden"
name="${_csrf.parameterName}"
value="${_csrf.token}" />
Cosa succede se manca il token CSRF?
Se il token CSRF manca o non è valido, Spring Security può bloccare la richiesta e restituire un errore, spesso un 403 Forbidden.
HTTP 403 Forbidden
Per questo motivo, quando crei una pagina di login personalizzata, devi sempre verificare che il token CSRF venga incluso correttamente nel form.
Best practice: non disabilitare CSRF solo per far funzionare il form. Prima controlla che il token sia presente e venga inviato correttamente.
Gestione degli errori di autenticazione
Quando l’autenticazione fallisce, possiamo reindirizzare l’utente alla pagina di login con un parametro di errore.
.failureUrl("/login?error=true")
Nel template, possiamo mostrare un messaggio se il parametro error è presente.
Con Thymeleaf
<div th:if="${param.error}">
<p>Username o password non validi.</p>
</div>
Con JSP
<c:if test="${param.error != null}">
<div>
<p>Username o password non validi.</p>
</div>
</c:if>
È meglio usare messaggi generici, senza specificare se il problema è lo username o la password. Questo evita di dare informazioni utili a un eventuale attaccante.
Sicurezza: preferisci messaggi come “Credenziali non valide” invece di “Username inesistente” o “Password errata”.
Parametri username e password
Per impostazione predefinita, Spring Security si aspetta che il form invii:
usernameper il nome utente;passwordper la password.
<input type="text" name="username">
<input type="password" name="password">
Se vuoi usare nomi diversi, puoi configurarli in Spring Security.
Parametri personalizzati
.formLogin(form -> form
.loginPage("/login")
.loginProcessingUrl("/login")
.usernameParameter("email")
.passwordParameter("secret")
.defaultSuccessUrl("/", true)
.failureUrl("/login?error=true")
)
In questo caso il form dovrà usare:
<input type="text" name="email">
<input type="password" name="secret">
Questa personalizzazione può essere utile quando l’utente effettua il login con email invece che con username.
Configurazione del logout
Il logout è un’altra parte importante della configurazione. Un esempio moderno è:
.logout(logout -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout=true")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID")
.permitAll()
)
Questa configurazione indica che:
- il logout avviene tramite
/logout; - dopo il logout l’utente viene reindirizzato a
/login?logout=true; - la sessione HTTP viene invalidata;
- il cookie
JSESSIONIDviene eliminato; - l’endpoint di logout è accessibile secondo la configurazione di sicurezza.
Form di logout con CSRF
Con CSRF attivo, il logout dovrebbe essere eseguito tramite form POST.
<form th:action="@{/logout}" method="post">
<input type="hidden"
th:name="${_csrf.parameterName}"
th:value="${_csrf.token}">
<button type="submit">Logout</button>
</form>
Messaggio di logout completato
<div th:if="${param.logout}">
<p>Logout eseguito correttamente.</p>
</div>
Nota importante: se CSRF è attivo, un semplice link
<a href="/logout">può non essere sufficiente o non essere la scelta corretta. È preferibile usare una form POST con token CSRF.
Homepage protetta dopo il login
Dopo il login, possiamo mostrare una pagina protetta accessibile solo agli utenti autenticati.
Controller home
package it.javaboss.security;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping("/")
public String home() {
return "index";
}
}
Template index.html con Thymeleaf
<!DOCTYPE html>
<html lang="it"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="https://www.thymeleaf.org/extras/spring-security">
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
<h1>Area riservata</h1>
<p>
Benvenuto:
<strong sec:authentication="name">utente</strong>
</p>
<form th:action="@{/logout}" method="post">
<input type="hidden"
th:name="${_csrf.parameterName}"
th:value="${_csrf.token}">
<button type="submit">Logout</button>
</form>
</body>
</html>
La pagina mostra il nome dell’utente autenticato e una form per eseguire il logout.
Esempio completo con Thymeleaf
Riepiloghiamo una configurazione moderna completa con Spring Boot, Spring Security e Thymeleaf.
SecurityConfig.java
package it.javaboss.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
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.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/login", "/css/**", "/js/**", "/images/**").permitAll()
.anyRequest().authenticated()
)
.formLogin(form -> form
.loginPage("/login")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/", true)
.failureUrl("/login?error=true")
.permitAll()
)
.logout(logout -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout=true")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID")
.permitAll()
);
return http.build();
}
@Bean
public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
UserDetails user = User.builder()
.username("mario")
.password(passwordEncoder.encode("password"))
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
LoginController.java
package it.javaboss.security;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class LoginController {
@GetMapping("/login")
public String login() {
return "login";
}
}
HomeController.java
package it.javaboss.security;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping("/")
public String index() {
return "index";
}
}
login.html
<!DOCTYPE html>
<html lang="it" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<h1>Login</h1>
<div th:if="${param.error}">
<p>Credenziali non valide.</p>
</div>
<div th:if="${param.logout}">
<p>Logout eseguito correttamente.</p>
</div>
<form th:action="@{/login}" method="post">
<div>
<label for="username">Username</label>
<input type="text" id="username" name="username" required autofocus>
</div>
<div>
<label for="password">Password</label>
<input type="password" id="password" name="password" required>
</div>
<input type="hidden"
th:name="${_csrf.parameterName}"
th:value="${_csrf.token}">
<button type="submit">Accedi</button>
</form>
</body>
</html>
index.html
<!DOCTYPE html>
<html lang="it"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="https://www.thymeleaf.org/extras/spring-security">
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
<h1>Homepage protetta</h1>
<p>
Utente autenticato:
<strong sec:authentication="name">utente</strong>
</p>
<form th:action="@{/logout}" method="post">
<input type="hidden"
th:name="${_csrf.parameterName}"
th:value="${_csrf.token}">
<button type="submit">Logout</button>
</form>
</body>
</html>
Esempio legacy con JSP
In molti progetti legacy, la maschera di login è realizzata con JSP. Anche in questo caso, i concetti sono gli stessi: form POST, parametri corretti, gestione dell’errore e token CSRF.
login.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title>Login</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/style.css" />
</head>
<body onload="document.f.username.focus();">
<c:if test="${param.error != null}">
<div>
<p>Credenziali non valide.</p>
</div>
</c:if>
<c:if test="${param.logout != null}">
<div>
<p>Logout eseguito correttamente.</p>
</div>
</c:if>
<form name="f" method="POST" action="${pageContext.request.contextPath}/login">
<div>
<h1>Login</h1>
<label for="username">Username</label>
<input type="text" id="username" name="username" />
<label for="password">Password</label>
<input type="password" id="password" name="password" />
<input type="hidden"
name="${_csrf.parameterName}"
value="${_csrf.token}" />
<input name="submit" type="submit" value="Accedi" />
</div>
</form>
</body>
</html>
index.jsp
<%@ taglib prefix="security"
uri="http://www.springframework.org/security/tags" %>
<html>
<body>
<h1>Homepage protetta</h1>
<h2>
Benvenuto:
<security:authentication property="principal.username" />
</h2>
<form action="${pageContext.request.contextPath}/logout" method="POST">
<input type="hidden"
name="${_csrf.parameterName}"
value="${_csrf.token}" />
<input type="submit" value="Logout" />
</form>
</body>
</html>
Nota legacy: nei progetti JSP più vecchi puoi trovare riferimenti a
j_username,j_passwordoj_spring_security_check. Nelle configurazioni moderne i valori comuni sonousername,passworde/login.
Configurazione XML legacy
Nei vecchi progetti Spring Security era comune configurare tutto tramite XML, per esempio nel file spring-security.xml.
Configurazione form-login XML
<http auto-config="true" use-expressions="true">
<form-login
login-page="/login.jsp"
default-target-url="/index.jsp"
authentication-failure-url="/login.jsp?error=true"
login-processing-url="/login" />
<logout
logout-url="/logout"
logout-success-url="/login.jsp?logout=true"
invalidate-session="true"
delete-cookies="JSESSIONID" />
<intercept-url pattern="/login*" access="isAnonymous()" />
<intercept-url pattern="/css/**" access="permitAll" />
<intercept-url pattern="/images/**" access="permitAll" />
<intercept-url pattern="/**" access="isAuthenticated()" />
</http>
Questa configurazione indica a Spring Security quale pagina JSP usare per il login, dove inviare il form, cosa fare in caso di errore e come gestire il logout.
Welcome file in web.xml
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
Questa parte è tipica delle web application Java tradizionali basate su WAR, JSP e descrittore web.xml.
WebSecurityConfigurerAdapter e migrazione
Molti tutorial scritti per Spring Security 4 o 5 usavano WebSecurityConfigurerAdapter.
Vecchio stile
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login", "/css/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll();
}
}
Nei progetti moderni è preferibile migrare verso SecurityFilterChain.
Nuovo stile
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/login", "/css/**").permitAll()
.anyRequest().authenticated()
)
.formLogin(form -> form
.loginPage("/login")
.permitAll()
);
return http.build();
}
}
La logica è molto simile, ma la configurazione è più esplicita e basata su bean.
Flusso completo del login personalizzato
Il flusso completo di una maschera di login personalizzata in Spring Security può essere riassunto così:
GET /area-riservata
↓
Utente non autenticato
↓
Redirect a /login
↓
Visualizzazione login.html
↓
POST /login con username, password e CSRF
↓
Spring Security autentica l’utente
↓
Successo → redirect alla homepage o alla pagina richiesta
Errore → redirect a /login?error=true
Il punto più importante è che l’URL /login ha due ruoli diversi:
GET /loginmostra la pagina di login;POST /loginprocessa le credenziali tramite Spring Security.
Errori comuni
Non permettere l’accesso alla pagina di login
Se la pagina di login richiede autenticazione, l’utente non potrà mai autenticarsi correttamente. Devi permettere l’accesso pubblico a /login.
.requestMatchers("/login").permitAll()
Bloccare CSS, immagini o JavaScript
Se le risorse statiche sono protette, la pagina di login può caricarsi senza stile, senza immagini o con funzionalità mancanti.
.requestMatchers("/css/**", "/js/**", "/images/**").permitAll()
Usare un action sbagliato nel form
Il form deve inviare le credenziali all’URL configurato con loginProcessingUrl.
<form th:action="@{/login}" method="post">
Dimenticare method=”post”
Il login deve essere inviato con metodo POST, non con GET.
Dimenticare il token CSRF
Se CSRF è attivo e il token non viene inviato, Spring Security può rifiutare la richiesta.
Usare nomi errati per username e password
Se il form usa email ma Spring Security si aspetta username, l’autenticazione può fallire. In quel caso bisogna configurare usernameParameter.
Esporre dettagli eccessivi negli errori
Non dire all’utente se è sbagliato lo username o la password. Usa un messaggio generico.
Usare un link GET per il logout con CSRF attivo
Con CSRF attivo, il logout dovrebbe essere eseguito tramite form POST con token CSRF.
Disabilitare CSRF senza motivo
Molti sviluppatori disabilitano CSRF per risolvere rapidamente un errore 403. In un’applicazione web con sessione, questa scelta può ridurre la sicurezza.
Best practice per login personalizzato in Spring Security
- Usa
SecurityFilterChainnei progetti moderni. - Permetti l’accesso pubblico a login e risorse statiche.
- Usa sempre
POSTper inviare il form di login. - Includi il token CSRF nel form.
- Usa messaggi di errore generici.
- Non disabilitare CSRF senza un motivo preciso.
- Usa
BCryptPasswordEncodero un encoder sicuro per le password. - Evita password in chiaro nel codice, tranne che in esempi didattici.
- Configura correttamente il logout.
- Usa HTTPS in produzione.
- Proteggi tutte le pagine riservate.
- Valuta rate limiting o protezioni contro brute force.
- Non mostrare informazioni sensibili nella pagina di errore.
- Testa login corretto, login fallito, logout e accesso a risorse protette.
Checklist di debug
| Problema | Controllo da fare |
|---|---|
| Errore 403 al login | Verifica token CSRF e metodo POST. |
| CSS non caricato | Permetti /css/** nelle regole di sicurezza. |
| Login sempre fallito | Controlla nomi dei parametri username e password. |
| Pagina login in loop | Verifica che /login sia accessibile a tutti. |
| Logout non funziona | Usa form POST con token CSRF. |
| Redirect sbagliato dopo login | Controlla defaultSuccessUrl e request salvata. |
| Errore template | Verifica posizione del file login.html o login.jsp. |
FAQ sul login personalizzato in Spring Security
Come creare una maschera di login personalizzata in Spring Security?
Devi creare una pagina di login, configurare formLogin() con loginPage(), permettere l’accesso pubblico alla pagina e inviare il form con metodo POST all’URL configurato con loginProcessingUrl().
Qual è l’URL predefinito per il login in Spring Security?
In una configurazione standard, il form viene inviato con POST a /login.
Quali sono i nomi predefiniti dei campi username e password?
I nomi predefiniti sono username e password.
Posso usare email al posto di username?
Sì. Puoi configurare usernameParameter("email") e usare un input con name="email".
Perché ricevo errore 403 quando invio il form di login?
Spesso il problema è l’assenza del token CSRF o l’uso di un metodo HTTP non corretto. Il form dovrebbe usare POST e includere il token CSRF.
Devo disabilitare CSRF per far funzionare il login?
No, normalmente non è necessario. È meglio includere correttamente il token CSRF nel form.
Come mostrare un messaggio di errore dopo login fallito?
Puoi configurare failureUrl("/login?error=true") e mostrare un messaggio nella pagina se il parametro error è presente.
Come configurare il logout?
Puoi usare logoutUrl("/logout"), logoutSuccessUrl("/login?logout=true"), invalidateHttpSession(true) e deleteCookies("JSESSIONID").
Il logout deve essere GET o POST?
Con CSRF attivo, il logout dovrebbe essere eseguito tramite POST e includere il token CSRF.
Posso usare JSP con Spring Security moderno?
Sì, ma per nuovi progetti Spring Boot spesso Thymeleaf è più semplice da configurare. JSP resta comune in applicazioni legacy.
Che fine ha fatto WebSecurityConfigurerAdapter?
Nei progetti moderni si preferisce configurare Spring Security dichiarando un bean SecurityFilterChain.
Come permettere CSS e immagini nella pagina di login?
Devi aggiungere regole come .requestMatchers("/css/**", "/images/**", "/js/**").permitAll().
Conclusione
Creare una maschera di login personalizzata in Spring Security è una delle prime personalizzazioni che si fanno in una web application reale. La pagina generata automaticamente da Spring Security è utile per test e prototipi, ma un progetto professionale richiede quasi sempre una form coerente con il design dell’applicazione.
Il meccanismo è semplice: si crea una pagina di login, si configura formLogin(), si permette l’accesso pubblico a login e risorse statiche, si inviano le credenziali con POST a /login e si include il token CSRF.
Nei progetti moderni è consigliabile usare SecurityFilterChain, Thymeleaf e configurazione Java. Nei progetti legacy è ancora possibile trovare JSP, XML, spring-security.xml, form-login e tag library di Spring Security.
Il punto più importante è non confondere la pagina di login con la logica di autenticazione: la pagina raccoglie username e password, ma è Spring Security a gestire il processo di autenticazione, sessione, CSRF, logout e accesso alle risorse protette.
Riassunto finale: una login page personalizzata in Spring Security deve essere pubblica, inviare un form POST all’URL corretto, usare i parametri attesi, includere il token CSRF e gestire correttamente errori e logout.