No puedo actualizar mi aplicación Spring Boot a 2.6.0 desde 2.5.7. Lanza el siguiente error.
2021-12-07T08:40:22,311 ERROR [restartedMain] osbSpringApplication.reportFailure:819|| Application run failed org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'webSecurityConfig': The requested bean is currently in creation: Is there an unresolvable circular reference? at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:355) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:227) De las notas de la versión spring-boot 2.6.0, está claro que las referencias circulares están deshabilitadas. Y se puede volver a habilitar con la propiedad spring.main.allow-circular-references = true . Pero me gustaría arreglar la referencia circular en primer lugar. ¿Alguien puede ayudarme a solucionar este problema? Encuentre la clase WebSecurityConfig a continuación,
@Configuration @EnableWebSecurity @SuppressWarnings({"PMD.SignatureDeclareThrowsException"}) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { private final UserDetailsService userDetailsService; public WebSecurityConfig(final UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } @Bean public BCryptPasswordEncoder bcryptPasswordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(final HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/resources/**", "/registration", "/css/**", "/js/**", "/h2-console/*").permitAll() .anyRequest().authenticated().and() .formLogin() .loginPage("/login").permitAll().and() .headers() .frameOptions().sameOrigin().and() .logout() .permitAll().and() .requiresChannel() .requestMatchers(r -> r.getHeader("X-Forwarded-Proto") != null) .requiresSecure(); } @Autowired public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(bcryptPasswordEncoder()); } }Mi código es de código abierto y se puede encontrar en https://github.com/surajcm/Poseidon . Intentaré solucionar el problema por mi cuenta y compartiré las actualizaciones si puedo resolver este problema.
El problema es el codificador de contraseñas. Se requiere para construir el UserDetailsService que inyecta en el constructor de la clase.
Puede romper el ciclo haciendo que el método de fábrica de frijoles sea static :
@Bean public static BCryptPasswordEncoder bcryptPasswordEncoder() { return new BCryptPasswordEncoder(); } También puede mover el método de fábrica a una clase de configuración diferente. Pero en mi opinión, su WebSecurityConfig es el lugar canónico para el método.
Como recibí un comentario que decía que estaba haciendo una configuración de seguridad personalizada, lo cual es una mala práctica, traté de solucionarlo por mi cuenta. Intenté eliminar el bean configureGlobal y agregué el proveedor de authenticationProvider en su lugar. Encuentre el código de muestra a continuación
@Configuration @EnableWebSecurity @SuppressWarnings({"PMD.SignatureDeclareThrowsException"}) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { private final UserDetailsService userDetailsService; public WebSecurityConfig(final UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } @Bean public BCryptPasswordEncoder bcryptPasswordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(final HttpSecurity http) throws Exception { //http.headers().frameOptions().disable(); http.csrf().disable(); http .authorizeRequests() .antMatchers("/resources/**", "/registration", "/css/**", "/js/**", "/img/**", "/h2-console/**", "/console/**").permitAll() .and().headers().frameOptions().sameOrigin(); http .authorizeRequests() .anyRequest().authenticated().and() .formLogin() .loginPage("/login").permitAll().and() .headers() .frameOptions().sameOrigin().and() .logout() .permitAll().and() .requiresChannel() .requestMatchers(r -> r.getHeader("X-Forwarded-Proto") != null) .requiresSecure(); } @Bean public AuthenticationProvider authenticationProvider() { var provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(userDetailsService); provider.setPasswordEncoder(bcryptPasswordEncoder()); return provider; } }