navinreddy20 / spring6yt

84 stars 58 forks source link

Circular Dependency error in Folder #36 #3

Open vrukshal opened 2 months ago

vrukshal commented 2 months ago

I am trying to learn spring boot along with this course and in #36 video when I declare variable @Autowired AuthenticationManager authManager; In my Service class, I am getting below error

The dependencies of some of the beans in the application context form a cycle:

┌─────┐ | securityConfig (field private org.springframework.security.core.userdetails.UserDetailsService com.example.auth_service.config.SecurityConfig.userDetailsService) ↑ ↓ | myUserDetailsSevice (field private org.springframework.security.authentication.AuthenticationManager com.example.auth_service.service.MyUserDetailsSevice.authManager) └─────┘

below is my code for security Config package com.example.auth_service.config;

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.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.security.web.SecurityFilterChain;

@Configuration @EnableWebSecurity public class SecurityConfig {

@Autowired
private UserDetailsService userDetailsService;

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

    return http.csrf(customizer -> customizer.disable()).
            authorizeHttpRequests(request -> request
                    .requestMatchers("createuser","login")
                    .permitAll()
                    .anyRequest().authenticated()).
            httpBasic(Customizer.withDefaults()).
            sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)).build();

}

@Bean
public DaoAuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
    provider.setPasswordEncoder(new BCryptPasswordEncoder(12));
    provider.setUserDetailsService(userDetailsService);
    return provider;
}

@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
    return config.getAuthenticationManager();
}

}

and below is code for Service class package com.example.auth_service.service;

import com.example.auth_service.entity.UserPrincipal; import com.example.auth_service.entity.Users; import com.example.auth_service.repository.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service;

@Service public class MyUserDetailsSevice implements UserDetailsService {

@Autowired
private UserRepository repo;

@Autowired
private AuthenticationManager authManager;

private BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(12);

public String verify(Users user) {
    Authentication authentication = authManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(),user.getPassword()));

    if(authentication.isAuthenticated())
        return "Success";
    return "Fail";
}

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

    Users user = repo.findByUsername(username);
    if(user==null)
        throw new UsernameNotFoundException("User 404");

    return new UserPrincipal(user);
}

public Users Register(Users user){
    user.setPassword(encoder.encode(user.getPassword()));
    return repo.save(user);
}

}

izeinnn commented 1 month ago

The dependencies of some of the beans in the application context form a cycle:

To avoid the circular dependency between SecurityConfig and MyUserDetailsService, pass AuthenticationManager to the verify() method as a parameter, and remove the @Autowired annotation

public String verify(Users user, AuthenticationManager authManager) { Authentication authentication = authManager.authenticate( new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()) ); return authentication.isAuthenticated() ? "Success" : "Fail"; }