My IDE reports two errors in the following class:
- WebSecurityConfigurerAdapter is a deprecated class;
- 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;
}
}
}