Ammodernare la mia configurazione di Spring Security

di il
4 risposte

Ammodernare la mia configurazione di Spring Security

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>

4 Risposte

  • Re: Ammodernare la mia configurazione di Spring Security

    iBaffiPro ha scritto:


    Ho creato una WebApp semplicissima, da terza elementare per intenderci, creata partendo da un progetto molto vecchio trovato Googlando
    Non mi pare proprio da "terza elementare" per tutto quello che hai chiesto (e mostrato) in questi mesi .... Ma non posso dire altro non potendo vedere il tutto ...

    iBaffiPro ha scritto:


    e l'obbiettivo è aggiornare il tutto all'ultimissima versione per estenderne il più possibile la longevità del programma.
    Guarda che "longevità" non vuol dire stare all'ultimissima versione di tutto quanto .... Riguarda più la manutenibilità e la gestibilità del progetto, oltre ovviamente alla "stabilità" generale di framework/librerie .... piuttosto che le ultime versioni in sé.

    Poi immagina ad esempio di voler mettere la webapp su un hosting "reale". Pensi che tutti gli hosting Tomcat/Java diano già adesso il supporto per Java 17? Quasi sicuramente no. Molto probabilmente la maggior parte è ancora su Java 8 e/o forse (con più fortuna) Java 11.

    iBaffiPro ha scritto:


    Mi piacerebbe aggiornare tutto alla versione 3 di Spring Boot ma non esiste ancora la versione ufficiale
    Consiglio proprio spassionato: dimentica per ora (e ancora per un bel po') Spring 3.

    iBaffiPro ha scritto:


    1) Cosa deve controllare/aggiornare quando voglio ammodernare la mia applicazione?
    Devi leggere attentamente la documentazione di Spring/Spring Boot, comprese le release note. Possono cambiare molte cose: "starter" di Boot in più o in meno, valori di default differenti per certe property, concetti cambiati leggermente, classi/metodi che sono diventati "deprecati", ecc... Lo sai solo LEGGENDO la documentazione.

    iBaffiPro ha scritto:


    2) Come si gestisce la crittografia delle password?
    Crittografia di che tipo? (simmetrica?) E a quale livello? Memorizzazione su DB? (ma non stai già usando il BCrypt? Che comunque è un hash, quindi NON crittografia reversibile).

    iBaffiPro ha scritto:


    3) Come si gestisce il tasto "ricorda la mia password" in Spring Boot?
    Sono poco ferrato su Spring Security. Se vuoi davvero approfondire la security in Spring, è sempre meglio un buon libro.

    iBaffiPro ha scritto:


    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?
    Beh, quanti import legati a JavaEE hai nella applicazione?

    Cerca in tutto il progetto nei tuoi sorgenti questa stringa come "espressione regolare":
    ^import\s+(javax\.annotation|javax\.batch|javax\.decorator|javax\.ejb|javax\.el|javax\.enterprise|javax\.faces|javax\.inject|javax\.interceptor|javax\.jms|javax\.json|javax\.mail|javax\.management|javax\.persistence|javax\.resource|javax\.security|javax\.servlet|javax\.transaction|javax\.validation|javax\.websocket|javax\.ws|javax\.xml)
    L'ho scritta al volo prendendo i package base di JavaEE.

    E comunque qualunque buon IDE è in grado di fare ricerche/sostituzioni "a tappeto" sul progetto. Quindi è il problema minore, anzi un non-problema ...

    iBaffiPro ha scritto:


    Posso fare la sostituzione già ora che uso 2.6.4 oppure sarebbe un errore?
    Cambiare verso jakarta.*** NO, perché Spring Boot 2 è ancora legato a Java EE, non Jakarta EE.

    iBaffiPro ha scritto:


    C'è scritto che alcune dipendenze potrebbero non essere compatibili con Spring Boot 3 ma io come faccio a scoprirlo?
    Di nuovo, LEGGENDO la documentazione.

    iBaffiPro ha scritto:


    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?
    Hai sicuramente fatto qualcosa di sbagliato/inappropriato a livello di dipendenze tra le classi "bean". È un tuo errore di "design" che dovresti correggere. Non mettendo il allow-circular-references a true.

    iBaffiPro ha scritto:


    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?!?!
    Probabilmente è un articolo fatto nel passato quando era più in uso XML rispetto alla Java Configuration di Spring. Nulla di ché ... si può (quasi) sicuramente trasporre nella Java Configuration.
  • Re: Ammodernare la mia configurazione di Spring Security

    È meglio che tu non possa vedere altro altrimenti ti metteresti a ridere e diresti che l’applicazione è da 'seconda elementare'. Nella mia applicazione si fa una sola cosa, si digitano stringhe e numeri in una pagina html e si riportano nel DBMS, nulla di più e nulla di meno. Per fare questo l’uso di Spring Boot non solo è sprecato ma penso sia controproducente perché quando escono le nuove versioni del Framework non si riesce ad aggiornare nulla. Spring Boot mi ha deluso davvero molto. Non si può dover editare il codice ad ogni aggiornamento del Framework, è una porcata immane. Tra qualche anno Spring Boot sarà spazzatura se continua su questa linea di pensiero.
    Sul discorso della longevità sono d’accordo ma oggi Spring Boot 1.x è vecchio, conviene usare Spring Boot 2.x, tra non molto sarà vecchio il 2.x e ci sarà solo il 3.x. Quando aggiorno la versione di Bootstrap o di jQuery sul sito mi limito a modificare un solo file, non il codice scritto da me nelle varie pagine statiche. Spring, Spring Boot 1, Spring Boot 2, Spring Boot 3, ecc… sono tutti framework acerbi se modificano continuamente il codice che il programmatore deve usare. A mio avviso deve ancora nascere un framework stabile di Java.
    Il mio obiettivo non è quello di essere vincolato ad un hosting provider. Da quest’ultimo mi aspetto un pezzetto di risorse del server e di inserire tutta l’infrastruttura per conto mio. Devo poter decidere di cambiare in serenità e velocemente server ogni anno secondo la convenienza. In locale con Docker si mette su un server in 3 secondi, deve esserci un sistema anche sui server reali.
    Ok, dimentico Spring Boot 3 ma non voglio lasciare la mia WebApp ferma a Spring Boot 2 quando esce il 3 e soprattutto mi rifiuto di non poter aggiornare a 2.6.4 come mi rifiuto a dover usare accrocchi strani per poterlo impiegare. Piuttosto cambio Framework e ne cerco un altro dove sia possibile aggiornare quando mi fa comodo. Andare a leggere la documentazione ogni volta che aggiorno un’App? Sai il tempo che richiede? Scherzi? Conviene non usare un framework se devo impiegare tutto questo tempo ad aggiornare.
    Per crittografare le password uso BCrypt ma tutti i metodi che trovi nella classe sono scopiazzati da internet, non mi sono inventato nulla per Spring Security.
    Un altro problema grave è la totale assenza di un supporto per Spring Security. Se un utente deve aggiornare la propria app deve farlo in tutta comodità altrimenti deve ricevere un supporto per l’aggiornamento altrimenti dov’è la convenienza nell’usare un framework. Io non programmo per vivere e per fortuna ma se lo facessi sarei in perdita prima ancora di accendere il computer se ogni volta che aggiorno devo perdere giorni e giorni per aggiornare. Purtroppo, non posso fare confronti con altri framework come Laravel, Angular, NodeJS, ecc… ma se sono tutti così sono delle gran porcate e non aiutano realmente il programmatore, non senza un supporto.
    Ho trovato il modo per trovare i javax con IntelliJ, c’è una funzione comodissima, avevi perfettamente ragione. L’IDE che sto usando mi piace davvero molto. Per ora non cambio nulla e resto sulla 2.6.4 ma in futuro lo farò sicuramente.
    Il merito al codice spring.main.allow-circular-references = true dov’è l’errore a tuo avviso? Ti ripeto che la mia applicazione preleva dati da alcuni form li elabora e li scrive nel database. Non fa altro. L’errore se c’è è in quelle classi che ho postato. In realtà esiste altro codice che ho preso dal framework ed è quello che uso nella classe dove ci sono i @RequestMapping ma non penso ci sia molto da vedere in quelle.
    Forse l’articolo sul tasto "ricordami" è fatto in passato ma io non ho trovato altro sai. Comunque, se Spring Security fosse un framework valido dovrebbe scrivere il codice per BCrypt e per il tasto "Ricorda la mia password" per Spring Boot 2 e per Spring Boot 3 senza tanti giri di parole, non ha senso dover dipendere da siti terzi come baeldung.com, fare ricerche su Google, è semplicemente ridicolo.
  • Re: Ammodernare la mia configurazione di Spring Security

    iBaffiPro ha scritto:


    perché quando escono le nuove versioni del Framework non si riesce ad aggiornare nulla.
    Ma chi l'ha detto ... (?)

    iBaffiPro ha scritto:


    Spring Boot mi ha deluso davvero molto. Non si può dover editare il codice ad ogni aggiornamento del Framework, è una porcata immane. Tra qualche anno Spring Boot sarà spazzatura se continua su questa linea di pensiero.
    Ma non è che c'è da cambiare tutto!!! Tutti concetti basilari di Spring/Boot sono e restano quelli, anche in Boot 3.x. Tutte le nozioni sui bean, scope dei bean, autowiring, component scanning, @Controller, @Service, @Repository, ecc... SONO quelli e difficilmente verrebbero cambiati (semmai ampliati/migliorati).
    Quindi ad un ipotetico passaggio a Boot 3.x NON devi certo riscrivere "tutto"!!

    iBaffiPro ha scritto:


    Sul discorso della longevità sono d’accordo ma oggi Spring Boot 1.x è vecchio, conviene usare Spring Boot 2.x, tra non molto sarà vecchio il 2.x e ci sarà solo il 3.x. Quando aggiorno la versione di Bootstrap o di jQuery sul sito mi limito a modificare un solo file, non il codice scritto da me nelle varie pagine statiche. Spring, Spring Boot 1, Spring Boot 2, Spring Boot 3, ecc… sono tutti framework acerbi se modificano continuamente il codice che il programmatore deve usare.
    RIbadisco quanto detto sopra ...

    iBaffiPro ha scritto:


    A mio avviso deve ancora nascere un framework stabile di Java.
    Di framework per webapp/web-service ne esistono svariati oltre a Spring/Spring Boot. Play Framework ad esempio ma anche quelli più "moderni" che in questi ultimi anni sono entrati in "competizione" con Spring Boot, tra cui: Quarkus, Micronaut, Helidon e mettiamoci anche Vert.x che però è molto più particolare/specifico.
    E sono tutti ottimi in generale, ciascuno con i loro punti di forza e peculiarità.

    iBaffiPro ha scritto:


    Piuttosto cambio Framework e ne cerco un altro dove sia possibile aggiornare quando mi fa comodo. Andare a leggere la documentazione ogni volta che aggiorno un’App? Sai il tempo che richiede? Scherzi? Conviene non usare un framework se devo impiegare tutto questo tempo ad aggiornare.
    Te lo ripeto ancora: in una applicazione "seria" i framework/librerie in generale (soprattutto i "grossi" framework, intendo) NON vanno aggiornati di versione così su due piedi come si sgranocchiano le noccioline ogni momento che si vuole ...

    E comunque: hai già dimostrato scarsa conoscenza di Spring/Boot e limitata conoscenza di molti dei concetti "avanzati" di Java e ... andresti ad esempio a scegliere es., per dire, Quarkus, che è basato sul Eclipse MicroProfile, di cui presumo non sai assolutamente nulla e ti ci vorrebbero mesi (sì, MESI) per leggere tutte le user guide (in realtà non servono tutte subito!) di Quarkus, che comunque sono molto ben scritte, di cui temo capiresti inizialmente forse il 30% ??

    Il punto è che per poter lavorare molto bene su tutte queste cose ci vuole molto studio ed "esercizio". E' chiaro che se in un mese ci puoi/vuoi impegnare es. 6 ore per studio/esercitazioni ... allora forse il "gioco non vale la candela" ...

    iBaffiPro ha scritto:


    Il merito al codice spring.main.allow-circular-references = true dov’è l’errore a tuo avviso? Ti ripeto che la mia applicazione preleva dati da alcuni form li elabora e li scrive nel database. Non fa altro. L’errore se c’è è in quelle classi che ho postato. In realtà esiste altro codice che ho preso dal framework ed è quello che uso nella classe dove ci sono i @RequestMapping ma non penso ci sia molto da vedere in quelle.
    Bisognerebbe vedere bene il tutto. E poterlo provare. Togli il spring.main.allow-circular-references e verifica dal log di Spring cosa dice (che dovrebbe dire qualcosa!). Ma abbassa il livello di logging di Spring a DEBUG o anche TRACE.
  • Re: Ammodernare la mia configurazione di Spring Security

    P.S.: Ho trovato l'errore:
    
        @Bean
        public BCryptPasswordEncoder metodoCrittografia() {
            return new BCryptPasswordEncoder();
        }
    
    Ora provo a cambiare jdk, versione di Spring Boot e fare un po' di prove... vediamo cosa ottengo...
Devi accedere o registrarti per scrivere nel forum
4 risposte