Update the Spring Security configuration class with Spring Boot 2.7.0

My IDE reports two errors in the following class:

  1. WebSecurityConfigurerAdapter is a deprecated class;
  2. Could not autowire. No beans of ‘DataSource’ type found.

Locally the code works but I would still like to update the class with the new specifications. The code “private DataSource dataSource;” by IntelliJ in red worries me a lot.

How should I rewrite this class?

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;

import javax.sql.DataSource;

@Configuration
@EnableWebSecurity
public class ConfigurazioneSpringSecurity extends WebSecurityConfigurerAdapter {

    @Autowired
    LivelliDeiRuoli livelliDeiRuoli;

    @Autowired
    GestioneUtentiSpringSecurity gestioneUtentiSpringSecurity;

    @Bean
    public static BCryptPasswordEncoder metodoCrittografia() {
        return new BCryptPasswordEncoder();
    }

    @Autowired
    public void crittografiaPassword(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(gestioneUtentiSpringSecurity).passwordEncoder(metodoCrittografia());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());

        http.authorizeRequests().antMatchers(
                "/",
                "/login",
                "/benvenuto",
                "/registrazione",
                "/registrazione-eseguita",
                "/cookie",
                "/contatti",
                "logout"
        ).permitAll();

        // ... etc...

        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");

        http.authorizeRequests().and() //
                .rememberMe().tokenRepository(this.persistentTokenRepository()) //
                .tokenValiditySeconds(365 * 24 * 60 * 60);
        http.authorizeRequests().antMatchers("/nome-pagina")
                .access("hasAnyRole('" + livelliDeiRuoli.elencoRuoli(2L) + "')");

        // ... etc...

    }

    @Autowired
    private DataSource dataSource;

    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl db = new JdbcTokenRepositoryImpl();
        db.setDataSource(dataSource);
        return db;
    }

    @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

}

I updated the class by reading the following official documentation but in the page I found there are deprecated classes and methods.

https://spring.io/blog/2022/02/21/spring-security-without-the-websecurityconfigureradapter

I think I have everything corrected but it remains to understand how to configure Spring Security so that the “remember my password” button works. I have marked the code with question marks. I use PostgreSQL as a database and I put the database connection parameters in the .properties files. Here is the new class code:

package it.applicazionijava.gestioneutenti.autenticazione_spring_security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
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.core.userdetails.jdbc.JdbcDaoImpl;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.provisioning.JdbcUserDetailsManager;
import org.springframework.security.provisioning.UserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;

import javax.sql.DataSource;

import static org.springframework.security.config.Customizer.withDefaults;

@Configuration
public class SecurityConfiguration {

    @Autowired
    LivelliDeiRuoli livelliDeiRuoli;

    @Autowired
    GestioneUtentiSpringSecurity gestioneUtentiSpringSecurity;
    
    // ??? (code 1)
    @Autowired
    private DataSource dataSource;

    // ??? (code 2)
    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl db = new JdbcTokenRepositoryImpl();
        db.setDataSource(dataSource);
        return db;
    }

    // ??? (code 3)
    /*@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }*/

    @Bean
    public static BCryptPasswordEncoder metodoCrittografia() {
        return new BCryptPasswordEncoder();
    }

    /*@Autowired
    public void crittografiaPassword(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(gestioneUtentiSpringSecurity).passwordEncoder(metodoCrittografia());
    }*/

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
        // I am in doubt whether to use the code above or the code below 
        // but the one above worked in the past and was not deprecated.
        // http.csrf().csrfTokenRepository(new HttpSessionCsrfTokenRepository());
        
        // ??? (code 4)
        http.authorizeRequests().and() //
                .rememberMe().tokenRepository(this.persistentTokenRepository()) //
                .tokenValiditySeconds(365 * 24 * 60 * 60);
                
        http.authorizeRequests().antMatchers(
                "/",
                "/login",
                "/benvenuto",
                "/registrazione",
                "/registrazione-eseguita",
                "/cookie",
                "/contatti",
                "logout"
        ).permitAll();

        http.authorizeRequests().antMatchers("/area-riservata")
                .access("hasAnyRole('" + livelliDeiRuoli.elencoRuoli(1L) + "')");

        http.authorizeRequests().antMatchers("/cambio-password")
                .access("hasAnyRole('" + livelliDeiRuoli.elencoRuoli(1L) + "')");

        http.authorizeRequests().antMatchers("/cambio-nome")
                .access("hasAnyRole('" + livelliDeiRuoli.elencoRuoli(1L) + "')");

        http.authorizeRequests().antMatchers("/cancella-utente")
                .access("isAuthenticated()");

        http.authorizeRequests().antMatchers("/gestione-utenti")
                .access("hasAnyRole('" + livelliDeiRuoli.elencoRuoli(2L) + "')");

        http.authorizeRequests().antMatchers("/gestione-ruoli")
                .access("hasAnyRole('" + livelliDeiRuoli.elencoRuoli(3L) + "')");

        http.authorizeRequests().antMatchers("/pannello-di-controllo")
                .access("hasAnyRole('" + livelliDeiRuoli.elencoRuoli(3L) + "')");

        http.authorizeRequests().antMatchers("/pagine-applicazione")
                .access("hasAnyRole('" + livelliDeiRuoli.elencoRuoli(3L) + "')");

        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");

        //http.authorizeHttpRequests((authz) -> authz.anyRequest().authenticated()).httpBasic(withDefaults());
        http.headers().frameOptions().sameOrigin();
        return http.build();
    }

}

With codes 1, 2, 3 and 4 I get a compile error:

java: method does not override or implement a method from a supertype

Without the codes 1, 2, 3 and 4 I get a WebApp startup error:

  .   ____          _            __ _ _
 /\ / ___'_ __ _ _(_)_ __  __ _    
( ( )___ | '_ | '_| | '_ / _` |    
 \/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |___, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.7.0)

2022-05-31 14:51:58.455  INFO 3768 --- [  restartedMain] i.a.g.GestioneUtentiApplication          : Starting GestioneUtentiApplication using Java 11.0.15 on EB-DESKTOP with PID 3768 (...targetclasses ...)
2022-05-31 14:51:58.456  INFO 3768 --- [  restartedMain] i.a.g.GestioneUtentiApplication          : The following 1 profile is active: "sviluppo"
2022-05-31 14:51:58.495  INFO 3768 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2022-05-31 14:51:58.496  INFO 3768 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2022-05-31 14:51:59.690  INFO 3768 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8443 (https) 8080 (http)
2022-05-31 14:51:59.703  INFO 3768 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-05-31 14:51:59.703  INFO 3768 --- [  restartedMain] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.63]
2022-05-31 14:51:59.762  INFO 3768 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/it]     : Initializing Spring embedded WebApplicationContext
2022-05-31 14:51:59.762  INFO 3768 --- [  restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1266 ms
2022-05-31 14:51:59.833  INFO 3768 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2022-05-31 14:51:59.967  INFO 3768 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2022-05-31 14:52:00.351  WARN 3768 --- [  restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'controlloPagineWeb': Unsatisfied dependency expressed through field 'authManager'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.authentication.AuthenticationManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
2022-05-31 14:52:00.352  INFO 3768 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2022-05-31 14:52:00.372  INFO 3768 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
2022-05-31 14:52:00.375  INFO 3768 --- [  restartedMain] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2022-05-31 14:52:00.385  INFO 3768 --- [  restartedMain] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-05-31 14:52:00.403 ERROR 3768 --- [  restartedMain] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Field authManager in it.applicazionijava.gestioneutenti.pagine_web_spring_boot.ControlloPagineWeb required a bean of type 'org.springframework.security.authentication.AuthenticationManager' that could not be found.

The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'org.springframework.security.authentication.AuthenticationManager' in your configuration.

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  7.437 s
[INFO] Finished at: 2022-05-31T14:52:00+02:00
[INFO] ------------------------------------------------------------------------

Process finished with exit code 0

I read these 2 pages and tried the codes but I don’t solve:

Consider defining a bean of type ‘org.springframework.security.authentication.AuthenticationManager’ in your configuration

https://www.codejava.net/frameworks/spring-boot/fix-websecurityconfigureradapter-deprecated

@Controller
public class ControlloPagineWeb {

    // ...

    @Autowired
    private AuthenticationManager authManager;

    public void login(HttpServletRequest req, String user, String pass) {
        UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(user, pass);
        Authentication auth = authManager.authenticate(authReq);
        SecurityContext sc = SecurityContextHolder.getContext();
        sc.setAuthentication(auth);
    }

    // ...

}

I also use this class in Spring Security (mine is not a REST application, I don’t use json):

package it.applicazionijava.gestioneutenti.autenticazione_spring_security;

import it.applicazionijava.gestioneutenti.database_jdbc.*;
import it.applicazionijava.gestioneutenti.validazione_form.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class GestioneUtentiSpringSecurity implements UserDetailsService {

    @Autowired
    private UtenteRepository utenteRepository;

    @Autowired
    private RuoloRepository ruoloRepository;

    @Autowired
    EseguiVariabiliDiSistema eseguiVariabiliDiSistema;
    
    @Autowired
    LivelliDeiRuoli livelliDeiRuoli;

    @Override
    public UserDetails loadUserByUsername(String nomeUtente) throws UsernameNotFoundException {

        Utente utente = trovaUtenteConPrivilegiDiAutenticazione(nomeUtente);

        if (utente == null) {
            throw new UsernameNotFoundException("L'utente " + nomeUtente + " non รจ stato trovato nel database.");
        }

        List<String> ruoliUtente = null;
        try {
            ruoliUtente = this.ruoloRepository.trovaRuoliUtente(utente.getId());
        }catch (Exception b){
            ruoliUtente = null;
        }

        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;
        }

        UserDetails userDetails = null;
        if((utente != null) && (ruoliUtente != null) && (grantList != null)){
            userDetails = (UserDetails) new User(utente.getNome(), utente.getPassword(), grantList);
        }
        return userDetails;
    }

    public Utente trovaUtenteConPrivilegiDiAutenticazione(String nomeUtente){
        try{
            Utente utente = utenteRepository.trovaUtente(nomeUtente);
            if(livelliDeiRuoli.requisitiUtenteConRuoloMassimo(utente)){
                return utente;
            } else{
                eseguiVariabiliDiSistema.trovaVariabileSenzaVerificaUtente(
                        new VariabileSistema(0L, "login", "")
                );
                if(eseguiVariabiliDiSistema.getVariabileDiSistema().getValore().equals("true")){
                    return utente;
                }else if(eseguiVariabiliDiSistema.getVariabileDiSistema().getValore().equals("false")){
                    return null;
                }else{
                    return null;
                }
            }
        }catch (Exception e){
            return null;
        }
    }

}

Leave a Comment