Fala pessoal,
Sou novato no java, estou com um projeto a fim de praticar/treinar e ao tentar fazer um método de autenticação com SpringBoot e JWT não estou conseguindo, atualmente ele nem deixa o projeto subir, da o erro abaixo:
APPLICATION FAILED TO START
***************************
Description:
Field authenticationManager in com.luan.config.SecurityConfig 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.
estou utilizando a versão 6.0.1 do Spring Security e a versão 0.9.1 do JWT conforme pom.xml abaixo:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</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-starter-security</artifactId>
</dependency>
A classe que eu suspeito estar com erro é essa abaixo:
@EnableWebSecurity
@Configuration
public class SecurityConfig {
@Autowired
private JWTUtil jwtUtil;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.addFilter(new JWTAuthenticationFilter(authenticationManager, jwtUtil));
http.httpBasic().and().authorizeHttpRequests()
.requestMatchers(HttpMethod.POST, "/postsblog/**").permitAll()
.requestMatchers(HttpMethod.GET).permitAll()
.requestMatchers(HttpMethod.DELETE).hasRole("ADMIN")
.requestMatchers(HttpMethod.PUT).permitAll()
.anyRequest().authenticated()
.and().csrf().disable()
.cors().disable();
return http.build();
}
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowedHeaders("*").allowedMethods("*").exposedHeaders("*");
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean(name = "authenticationManager")
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
}
Mais especificamente, acredito que seja algum problema no ultimo método, o AuthenticationManagerBuilder, já tentei resolver de algumas formas e não consegui, pesquisando na internet só encontrei conteudo com Spring Security antigo extendendo o WebSecurityConfigAdapter.
Se alguém puder ajudar, agradeço desde já.
Provavelmente isso acontece porquê este método não fornece um bean válido, pois o retorno dele é void, normalmente ele deveria retornar uma instância de um objeto do tipo AuthenticationManager
.
Nas versões mais recentes do Spring como a 3 por exemplo, é algo semelhante a isso que é implementado para fornecer um bean válido:
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
Como você está estudando e aprendendo sobre, no github você consegue encontrar diversos projetos de exemplo que podem te orientar em alguns caminhos.
1 curtida
Primeiramnete obrigado pela ajuda, tentei fazer a alteração conforme sugeriu, mas segue dando erro, mudou o erro.
Já tentei encontrar soluções no Git Hub, em outros foruns mas nao consegui, estou travado aqui a um bom tempo. agora está com o erro abaixo, saberia me dizer onde está o problema no meu codigo?
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
┌──->──┐
| securityConfig (field private org.springframework.security.authentication.AuthenticationManager com.luan.config.SecurityConfig.authenticationManager)
└──<-──┘
Action:
Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.
Minha classe SecurityConfi está assim:
@EnableWebSecurity
@Configuration
public class SecurityConfig {
@Autowired
private JWTUtil jwtUtil;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.addFilter(new JWTAuthenticationFilter(authenticationManager, jwtUtil));
http.httpBasic().and().authorizeHttpRequests().requestMatchers(HttpMethod.POST, "/postsblog/**").permitAll()
.requestMatchers(HttpMethod.GET).permitAll().requestMatchers(HttpMethod.DELETE).hasRole("ADMIN")
.requestMatchers(HttpMethod.PUT).permitAll().anyRequest().authenticated().and().csrf().disable().cors()
.disable();
return http.build();
}
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowedHeaders("*").allowedMethods("*").exposedHeaders("*");
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration)
throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
}
Se você observar e ler o erro ele diz claramente que você tem uma referência cíclica!
Você não pode solicitar uma instancia do AuthenticationManager
na mesma classe em que você habilita a construção do Bean
.
Estava bem na minha cara o motivo, kkkkkkk
@Jonathan_Medeiros Obrigado!
Não sei se meu código ficou 100% certo, mas está funcional, vou deixar abaixo como ficou quem sabe pode ser útil para alguem no futuro.
´´´
@EnableWebSecurity
@Configuration
public class SecurityConfig {
@Autowired
private JWTUtil jwtUtil;
@Autowired
private UserDetailsService userDetailsService;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.headers().frameOptions().disable();
http.addFilter(new JWTAuthenticationFilter(authenticationManager(http.getSharedObject(AuthenticationConfiguration.class)), jwtUtil));
http.addFilter(new JWTAuthorizationFilter(authenticationManager(http.getSharedObject(AuthenticationConfiguration.class)), jwtUtil, userDetailsService));
http.httpBasic().and().authorizeHttpRequests()
.requestMatchers(HttpMethod.POST, "/login").permitAll()
.requestMatchers(HttpMethod.GET).permitAll()
.requestMatchers(HttpMethod.GET, "/h2-console/**").permitAll()
.anyRequest().authenticated().and().csrf().disable().cors().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
return http.build();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowedHeaders("*").allowedMethods("*").exposedHeaders("*");
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
´´´