Ciao a tutti,
Ho creato una WebApp semplicissima, da terza elementare per intenderci, creata partendo da un progetto molto vecchio trovato Googlando e l'obbiettivo è aggiornare il tutto all'ultimissima versione per estenderne il più possibile la longevità del programma. Mi piacerebbe aggiornare tutto alla versione 3 di Spring Boot ma non esiste ancora la versione ufficiale così, per ora, mi fermo alla 2.6.4. L'obiettivo è duplice, sperimentare un aggiornamento della mia applicazione e renderla il più possibile longeva. Fortunatamente ho la possibilità di aggiornare all'ultima versione di Spring Boot perché la mia WebApp è da terza elementare, non uso dipendenze particolari. Ho aperto la discussione per fare essenzialmente tre domande:
1) Cosa deve controllare/aggiornare quando voglio ammodernare la mia applicazione?
2) Come si gestisce la crittografia delle password?
3) Come si gestisce il tasto "ricorda la mia password" in Spring Boot?
PUNTO 1
https://spring.io/blog/2022/01/20/spring-boot-3-0-0-m1-is-now-available
Se si usa Spring Boot 3 si deve usare la JDK 17 quindi si aggiorna Java e va bene.
Poi c'è scritto di sostituire javax con jakarta e questo è un lavorone, non c'è un metodo più rapido su IntelliJ IDEA?
Posso fare la sostituzione già ora che uso 2.6.4 oppure sarebbe un errore?
C'è scritto che alcune dipendenze potrebbero non essere compatibili con Spring Boot 3 ma io come faccio a scoprirlo?
Quali classi/file devo controllare bene per passare all'ultima versione di Spring Boot oltre a quelli che ho allegato al post?
PUNTO 2
Questo punto è un grosso problema perché la soluzione che uso ora funziona ma mi costringe ad aggiungere nei file .properties questa stringa:
spring.main.allow-circular-references=true
Quindi c'è qualche impostazione di Spring Security che non è ottimale. Come risolvo?
PUNTO 3
https://www.baeldung.com/spring-security-persistent-remember-me
Questo è un problema ancora più grande perché su internet trovo una pagina recentissima che illustra come creare il tasto "ricordami" ma non usa i @Bean e questo mi lascia perplesso. L'uso dei @Bean non era un sistema alternativo, moderno, preferibile rispetto all'xml?!?! Con Spring Boot 3 facciamo retromarcia!?!?!
Grazie per il supporto
ALLEGATI
// Configurazione di Spring Security.
@Configuration
@EnableWebSecurity
public class ConfigurazioneSpringSecurity extends WebSecurityConfigurerAdapter {
// Metodi per la gestione dell'utente autenticato.
@Autowired
GestioneUtentiSpringSecurity gestioneUtentiSpringSecurity;
// 1) Metodo per crittografare la password >> ?????????????
@Bean
public BCryptPasswordEncoder metodoCrittografia() {
return new BCryptPasswordEncoder();
}
@Autowired
public void crittografiaPassword(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(gestioneUtentiSpringSecurity).passwordEncoder(metodoCrittografia());
}
// 2.a) Pulsante "Ricordami" (l'utente non deve inserire ogni volta la password di login) >> ?????????????
@Autowired
private DataSource dataSource;
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl db = new JdbcTokenRepositoryImpl();
db.setDataSource(dataSource);
return db;
}
// Se l'utente cambia la password il pulsante "Ricordami" continua a funzionare.
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
// Configurazione di Spring Security.
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().antMatchers(
"/",
"/login",
"/benvenuto",
"/registrazione",
"/registrazione-eseguita",
"/pagine-applicazione"
).permitAll();
http.authorizeRequests().antMatchers("/area-riservata")
.access("hasAnyRole('" + livelliDeiRuoli.elencoRuoli(1L) + "')");
// ... ecc...
http.authorizeRequests().and().exceptionHandling().accessDeniedPage("/errore-403");
http.authorizeRequests().and().formLogin()
.loginProcessingUrl("/pagina-login")
.loginPage("/login")
.defaultSuccessUrl("/")
.failureUrl("/login?errore=true")
.usernameParameter("username")
.passwordParameter("password")
.and().logout().logoutUrl("/pagina-logout")
.logoutSuccessUrl("/login?logout=true");
// 2.b) Pulsante "Ricordami" (l'utente non deve inserire ogni volta la password di login) >> ?????????????
http.authorizeRequests().and()
.rememberMe().tokenRepository(this.persistentTokenRepository())
.tokenValiditySeconds(365 * 24 * 60 * 60);
}
}
// Creazione utente autenticato.
@Service
public class GestioneUtentiSpringSecurity implements UserDetailsService {
@Autowired
private UtenteRepository utenteRepository;
@Autowired
private RuoloRepository ruoloRepository;
@Autowired
//...
// Creazione utente autenticato
@Override
public UserDetails loadUserByUsername(String nomeUtente) throws UsernameNotFoundException {
// Si cerca l'utente nel database
Utente utente = trovaUtenteConPrivilegiDiAutenticazione(nomeUtente);
if (utente == null) {
// System.out.println("L'utente " + nomeUtente + " non è stato trovato!");
throw new UsernameNotFoundException("L'utente " + nomeUtente + " non è stato trovato nel database.");
}
// Si cercano i ruoli dell'utente
List<String> ruoliUtente = null;
try {
ruoliUtente = this.ruoloRepository.trovaRuoliUtente(utente.getId());
}catch (Exception b){
ruoliUtente = null;
}
// Si caricano in una lista di oggetti GrantedAuthority i ruoli di un dato utente.
// GrantedAuthority è una classe di Spring Security che contiene i privilegi di un utente.
List<GrantedAuthority> grantList = null;
try{
grantList = new ArrayList<GrantedAuthority>();
if (ruoliUtente != null) {
for (String ruolo : ruoliUtente) {
GrantedAuthority authority = new SimpleGrantedAuthority(ruolo);
grantList.add(authority);
}
}
}catch (Exception c){
grantList = null;
}
// Si crea un oggetto specifico di Spring Security che rappresenta l'utente autenticato. Questo oggetto contiene 3
// informazioni: nome utente, password e privilegi. Questi ultimi, in questa applicazione si fanno coincidere
// con i ruoli.
UserDetails userDetails = null;
if((utente != null) && (ruoliUtente != null) && (grantList != null)){
userDetails = (UserDetails) new User(utente.getNome(), utente.getPassword(), grantList);
}
return userDetails;
}
// Si cerca l'utente nel database
public Utente trovaUtenteConPrivilegiDiAutenticazione(String nomeUtente){
// ...
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.4</version>
<relativePath/> <!--/* cerca genitore dal repository */-->
</parent>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<packaging>war</packaging>
<name>...</name>
<description>...</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<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.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.1</version>
</dependency>
</dependencies>
<build>
<finalName>gestioneutenti</finalName>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<packagingExcludes>
WEB-INF/classes/it/...
</packagingExcludes>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>