Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No qualifying bean of type 'org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder' available

I am using BCryptPasswordEncoder to encode my password but when i use its encode function to encode the password in my save function in UserService class it gives me this error:

Error creating bean with name 'userController': Unsatisfied dependency expressed through field 'userServiceInter'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService': Unsatisfied dependency expressed through field 'crypt'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

When i remove this it works but the password is not encoded.

UserService class:

   @Service
   public class UserService implements UserServiceInterface{

@Autowired
UserRepository repo;

@Autowired
BCryptPasswordEncoder crypt;

@Autowired
RoleRepository roleRepo;

public void save(User user) {


        user.setPassword(crypt.encode(user.getPassword()));
        Role role = roleRepo.findByRole("USER");
        user.setRoles(new HashSet<Role>(Arrays.asList(role)));
        repo.save(user);


   }

@Override
public User findByUsername(String userName) {

    User user = repo.findByUserName(userName);
    return user;

}

    }

UserServiceInterface:

   @Service
    public interface UserServiceInterface {


public void save(User user);

public User findByUsername(String userName);

    }

SecurityConfiguration:

   @Configuration
   @EnableWebSecurity
    public class SecurityConfiguration extends 
   WebSecurityConfigurerAdapter {

@Autowired
UserPrincipleDetailsService user;

@Autowired
private SimpleAuthenticationSuccessHandler successHandler;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws 
    Exception {

    auth.authenticationProvider(daoAuthenticationProvider());


}

@Override
protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()

        .antMatchers("/assets/css/**").permitAll()
        .antMatchers("/img/**").permitAll()
        .antMatchers("/home").permitAll()
        .antMatchers("/register/**").permitAll()
        .antMatchers("/registerUser").permitAll()
        .antMatchers("/admin/**").hasRole("ADMIN")
        .antMatchers("/user/**").hasAnyRole("ADMIN","USER")
        .anyRequest().authenticated()
        .and()
        .csrf().disable()
        .formLogin()
        .successHandler(successHandler)
        .loginPage("/home").permitAll()
        .loginProcessingUrl("/signin")
        .failureUrl("/home?error=true")


        .and()
        .logout().logoutRequestMatcher(new 
    AntPathRequestMatcher("/logout"))
        .logoutSuccessUrl("/home")
        .and()
        .exceptionHandling().accessDeniedPage("/home");

}

@Bean
DaoAuthenticationProvider daoAuthenticationProvider() {

    DaoAuthenticationProvider dao = new 
    DaoAuthenticationProvider();
    dao.setPasswordEncoder(passwordEncoder());
    dao.setUserDetailsService(user);

    return dao;


}

@Bean
PasswordEncoder passwordEncoder() {

    return new BCryptPasswordEncoder();
}

}
like image 925
Pariskrit A. Moktan Avatar asked Oct 02 '19 13:10

Pariskrit A. Moktan


2 Answers

change

@Autowired
BCryptPasswordEncoder crypt;

to

@Autowired
PasswordEncoder crypt

or change passwordEncoder method

@Bean
BCryptPasswordEncoder passwordEncoder() {

    return new BCryptPasswordEncoder();
}
like image 81
Shailesh Chandra Avatar answered Nov 11 '22 06:11

Shailesh Chandra


I agree Shailesh answer is 100% acceptable. If you wants to know

meaning of "No qualifying bean of type"

From below code

@Bean
PasswordEncoder passwordEncoder() 
{
    return new BCryptPasswordEncoder();
}

Definitely bean is created with the name passwordEncoder of type PasswordEncoder.

But

@Autowired
BCryptPasswordEncoder crypt;

Above code asking spring container to inject a bean of type BCryptPasswordEncoder.
(Note: passwordEncoder bean may be instance of BCryptPasswordEncoder but bean is of type PasswordEncoder and hence there is no bean of type BCryptPasswordEncoder)

Hence exception
No qualifying bean of type 'org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder' available

  1. Hence you can autowire bean of name passwordEncoder to a field of type PasswordEncoder.
@Autowired
PasswordEncoder crypt;
  1. Also you can get bean by name passwordEncoder from application context
@Autowired
ApplicationContext context;

inYourMethod()
{
   PasswordEncoder crypt = context.getBean("passwordEncoder");
}




For Quick understanding of @Bean, @Autowired and @Qualifier Simple 6 cases that explains very well

Case 1: Created bean type and Autowired field's type are Different - [This Will not work]
(No qualifying bean of type BCryptPasswordEncoder available)

@Autowired
BCryptPasswordEncoder passwordEncoder;

@Bean
PasswordEncoder passwordEncoder() 
{
    return new BCryptPasswordEncoder();
}


Case 2: Created bean type and Autowired field's type are same - [This Will not work]
@Autowired
PasswordEncoder passwordEncoder;

@Bean
PasswordEncoder passwordEncoder() 
{
    return new BCryptPasswordEncoder();
}


Case 3: Autowired field's type is super type of created bean - [This will work] Is bean created is of type BCryptPasswordEncoder - Yes
Is bean created is of type PasswordEncoder - Yes
@Autowired
PasswordEncoder passwordEncoder;

@Bean
BCryptPasswordEncoder passwordEncoder() 
{
    return new BCryptPasswordEncoder();
}


Case 4: Multiple beans of same type and without @Qualifier - [This will not work]

NoUniqueBeanDefinitionException: No qualifying bean of type 'o.s.s.c.p.PasswordEncoder' available: expected single matching bean but found 2: bcryptPasswordEncoder,md4PasswordEncoder

@Autowired
PasswordEncoder bcrypt;

@Autowired
PasswordEncoder md4;

@Bean
public PasswordEncoder bcryptPasswordEncoder() 
{
    return new BCryptPasswordEncoder();
}

@Bean
public PasswordEncoder md4PasswordEncoder() 
{
    return new Md4PasswordEncoder();
}


Case 5: Multiple beans of same type and with @Qualifier - [This will work]
Qualifier helps in selecting bean for injection
@Autowired
@Qualifier("bcryptPasswordEncoder")
PasswordEncoder bcrypt;

@Autowired
@Qualifier("md4PasswordEncoder")
PasswordEncoder md4;

@Bean
public PasswordEncoder bcryptPasswordEncoder() 
{
    return new BCryptPasswordEncoder();
}

@Bean
public PasswordEncoder md4PasswordEncoder() 
{
    return new Md4PasswordEncoder();
}


Case 6: Multiple beans of same type and without @Qualifier but field name same as bean name - [This will work]

Here Field name acts as qualifier and helps when there are multiple beans of same type.

@Autowired
PasswordEncoder bcryptPasswordEncoder;

@Autowired
PasswordEncoder md4PasswordEncoder;

@Bean
public PasswordEncoder bcryptPasswordEncoder() 
{
    return new BCryptPasswordEncoder();
}

@Bean
public PasswordEncoder md4PasswordEncoder() 
{
    return new Md4PasswordEncoder();
}
like image 20
PraveenKumar Lalasangi Avatar answered Nov 11 '22 08:11

PraveenKumar Lalasangi