没有类型为'org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder'的合格Bean

时间:2019-10-02 13:30:14

标签: java spring-boot spring-security

我正在使用BCryptPasswordEncoder编码我的密码,但是当我使用它的encoding函数在UserService类的save函数中对密码进行编码时,会出现此错误:

  

创建名称为'userController'的bean时出错:通过字段'userServiceInter'表示的不满意的依赖关系;嵌套的异常是org.springframework.beans.factory.UnsatisfiedDependencyException:创建名称为'userService'的bean时出错:通过字段'crypt'表示的不满足的依赖关系;嵌套的异常是org.springframework.beans.factory.NoSuchBeanDefinitionException:没有类型为“ org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder”的合格Bean:应该至少有1个有资格作为自动装配候选的Bean。依赖注释:{@ org.springframework.beans.factory.annotation.Autowired(required = true)}

当我删除它时,它可以工作,但密码未编码。

UserService类:

   @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();
}

}

3 个答案:

答案 0 :(得分:1)

更改

@Autowired
BCryptPasswordEncoder crypt;

@Autowired
PasswordEncoder crypt

或更改passwordEncoder方法

@Bean
BCryptPasswordEncoder passwordEncoder() {

    return new BCryptPasswordEncoder();
}

答案 1 :(得分:1)

我同意Shailesh的回答是100%可以接受的。如果您想知道

“没有类型的合格Bean”的含义

从下面的代码

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

使用类型 passwordEncoder名称 PasswordEncoder绝对创建

但是

@Autowired
BCryptPasswordEncoder crypt;

以上代码要求Spring容器注入类型为BCryptPasswordEncoder的bean。
(注意:passwordEncoder bean可能是BCryptPasswordEncoder的实例,但bean是PasswordEncoder类型的,因此没有BCryptPasswordEncoder类型的bean)

  

因此例外
  没有类型的合格Bean 'org.springframework.security.crypto.bcrypt。 BCryptPasswordEncoder '可用

  1. 因此,您可以将名称为passwordEncoder的bean自动连接到类型为PasswordEncoder的字段。
@Autowired
PasswordEncoder crypt;
  1. 此外,您还可以从应用程序上下文中通过名称passwordEncoder获取bean
@Autowired
ApplicationContext context;

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




为了快速理解@Bean@Autowired@Qualifier简单的6种情况,它们解释得很好

情况1:创建的bean类型和“自动连接”字段的类型不同-[此操作将无效]
(没有可用的BCryptPasswordEncoder类型的合格Bean)

@Autowired
BCryptPasswordEncoder passwordEncoder;

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


案例2:创建的bean类型和“自动连接”字段的类型相同-[此操作无效]

@Autowired
PasswordEncoder passwordEncoder;

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


案例3:“自动装配”字段的类型是所创建bean的超级类型-[这将起作用] 是创建的Bean的类型为BCryptPasswordEncoder-是
是否创建了类型为PasswordEncoder的bean-是

@Autowired
PasswordEncoder passwordEncoder;

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


案例4:多个相同类型且没有@Qualifier的bean-[这将不起作用]

  

NoUniqueBeanDefinitionException:没有类型为'o.s.s.c.p.PasswordEncoder'的合格Bean:预期为单个匹配的Bean,但找到2:bcryptPasswordEncoder,md4PasswordEncoder

@Autowired
PasswordEncoder bcrypt;

@Autowired
PasswordEncoder md4;

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

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


案例5:具有@Qualifier且具有相同类型的多个bean-[这将起作用]
限定词有助于选择要注入的豆

@Autowired
@Qualifier("bcryptPasswordEncoder")
PasswordEncoder bcrypt;

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

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

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


案例6:多个具有相同类型且没有@Qualifier但字段名称与bean名称相同的bean-[这将起作用]

在此,字段名称用作限定符,当有多个相同类型的bean时会提供帮助。

@Autowired
PasswordEncoder bcryptPasswordEncoder;

@Autowired
PasswordEncoder md4PasswordEncoder;

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

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

答案 2 :(得分:0)

在您的applicationContext.xml中添加此行,以供开发人员使用xml。

const SCREEN_WIDTH = Dimensions.get('window').width;

const Screen = (props) => (
  <View style={styles.splashBox}>        
    <Animatable.View animation="fadeIn" easing="ease-in" style={styles.boxImg}>
      <TouchableOpacity
        onPress={() => {
          this.props.navigation.navigate('Top Tabs', {
            screen: 'Tab 0',
          });
        }}>
        <Image
          style={styles.mainImg}
          source={{
            uri: props.imageUrl,
          }}
        />
      </TouchableOpacity>
    </Animatable.View>
  </View>
);

export default class Home extends Component {
  SCREENS = [
    <Screen imageUrl="https://i.imgur.com/Ew5iwzJ.jpg" />,
    <Screen imageUrl="https://i.imgur.com/Cxn6qVX.jpg" />,
  ];

  constructor(props) {
    super(props);
    this.state = {
      activeTab: 0,
    };
  }

  render() {
    return (
      <ScrollView showsVerticalScrollIndicator={false}>
        <View style={styles.mcontainer}>
          <View style={styles.container}>
            <Carousel
              ref={(ref) => (this.carouselRef = ref)}
              data={this.SCREENS}
              renderItem={({item}) => item}
              onSnapToItem={(i) => this.setState({activeTab: i})}
              sliderWidth={SCREEN_WIDTH}
              itemWidth={375}
/>