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:
@Configuration
@EnableWebSecurity
public class ConfigurazioneSpringSecurity {
@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)
@Override
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().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().antMatchers("/page1")
.access("hasAnyRole('" + livelliDeiRuoli.elencoRuoli(1L) + "')");
http.authorizeRequests().antMatchers("/page2")
.access("hasAnyRole('" + livelliDeiRuoli.elencoRuoli(2L) + "')");
// http. etc...
http.authorizeHttpRequests((authz) -> authz.anyRequest().authenticated()).httpBasic(withDefaults());
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 (...\target\classes ...)
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 believe it is some bug in the framework. I also opened a Stackoverflow thread with no success.
https://stackoverflow.com/questions/72427751/update-the-spring-security-configuration-class-with-spring-boot-2-7-0
Thanks for the support Federico
Comment From: rwinch
Thanks for getting in touch, but as you probably guessed since you also created a ticket on StackOverflow, it feels like this is a question that would be better suited to Stack Overflow. Please work with the community on finding an answer to your questions.
Comment From: fedegibut
On the other site I get no answer.
Comment From: fedegibut
Dear rwinch, This is not a stackoverflow question. I opened the discussion on that forum but I have not received any response. The documentation does not allow you to understand how to use your framework or your framework does not work and has some bugs. If you deprecate a class you should explain how to fix the framework code. I don't know if the problem is the documentation or the code. I didn't create Spring Security. I am also surprised not to see an answer from you. If you know Spring Security you can answer my question in seconds. If you do not want to answer this question because you consider me an unbearable or unpleasant person is another matter. I can't solve this problem myself because I didn't write Spring Security myself.
Comment From: fedegibut
It has been 3 months since I opened the discussion. Nobody knows how to log in automatically after registration, or after password change or name change. Why don't the Spring Boot developers explain how to do this? Why is there no comprehensive technical documentation?
https://stackoverflow.com/questions/72427751/update-the-spring-security-configuration-class-with-spring-boot-2-7-3
With the old version of Spring Boot I added a very convenient login() method to the class marked with the @Controller annotation.
It seems to me a big mistake to mark a class as deprecated and not explain what is to be used in place of it.
@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);
}
// login after registratiom:
login(
request,
user,
password
);
// with the new version of spring boot and spring security everything is an unknown... :(
Comment From: fedegibut
Thanks for getting in touch, but as you probably guessed since you also created a ticket on StackOverflow, it feels like this is a question that would be better suited to Stack Overflow. Please work with the community on finding an answer to your questions.
@rwinch It has been 3 months since I opened the discussion!
Don't you think there is some problem with the new version or something important is missing from the documentation?
You dismissed my call for help right away.