【问题标题】:Unable to implement CustomAuthenticationProvider with Spring Security: BeanCreationException while autowiring无法使用 Spring Security 实现 CustomAuthenticationProvider:自动装配时出现 BeanCreationException
【发布时间】:2020-03-08 15:33:51
【问题描述】:

我正在 Spring Security 中实现 CustomAuthenticationProvider。我创建了实现 AuthenticationProvider 的 CustomAuthenticationProvider 类。但是,当我在我的 SecurityConfiguration 类中定义这个 CustomAuthenticationProvider 并自动装配它时,应用程序会抛出以下错误:

2020-03-08 19:27:42 [main] ERROR o.s.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'securityConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.highrise.isimwebapp.config.customauth.CustomAuthenticationProvider com.highrise.isimwebapp.config.SecurityConfiguration.authProvider; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.highrise.isimwebapp.config.customauth.CustomAuthenticationProvider] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

我在我的 CustomAuthenticationProvider 类中包含了 @Component 注释。此外,定义此类的包包含在@ComponentScan 中。上下文没有拾取 CustomAuthenticationProvider bean。其他已定义的类已成功地被 @ComponentScan 中定义的上下文拾取,并且在其自动装配的对象上没有收到此类错误。我这边可能有什么问题?任何有关如何解决此问题的帮助将不胜感激。

CustomAuthenticationProvider.java

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    // TODO Auto-generated method stub
    String name = authentication.getName();
    String password = authentication.getCredentials().toString();
    if(name.equalsIgnoreCase("testuser1") && password.equalsIgnoreCase("demo"))
        return new UsernamePasswordAuthenticationToken(name, password);
    else
        throw new BadCredentialsException("Authentication failed");
}

@Override
public boolean supports(Class<?> authentication) {
    // TODO Auto-generated method stub
    return authentication.equals(UsernamePasswordAuthenticationToken.class);
}

}

SecurityConfiguration.java

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Autowired
private CustomAuthenticationProvider authProvider;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(authProvider);
}

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

  http.authorizeRequests()
    .antMatchers("/resources/**").permitAll()
    .antMatchers("/icon/**").permitAll()
    .anyRequest().authenticated()
    .and().formLogin().loginPage("/login").usernameParameter("username").passwordParameter("password").permitAll().defaultSuccessUrl("/persons/listall")
    .and().csrf().disable();

}
}

SpringWebConfig.java

@EnableWebMvc
@Configuration
@ComponentScan({ "com.highrise.isimwebapp.config", "com.highrise.isimwebapp.config.customauth", "com.highrise.isimwebapp.config.servlet3", "com.highrise.isimwebapp.web", "com.highrise.isimwebapp.service", "com.highrise.isimwebapp.dao",
    "com.highrise.isimwebapp.exception", "com.highrise.isimwebapp.validator" })
public class SpringWebConfig extends WebMvcConfigurerAdapter {

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}

@Bean
public InternalResourceViewResolver viewResolver() {
    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
    viewResolver.setViewClass(JstlView.class);
    viewResolver.setPrefix("/WEB-INF/views/jsp/");
    viewResolver.setSuffix(".jsp");
    return viewResolver;
}

@Bean
public ResourceBundleMessageSource messageSource() {
    ResourceBundleMessageSource rb = new ResourceBundleMessageSource();
    rb.setBasenames(new String[] { "messages/messages", "messages/validation" });
    return rb;
}

}

【问题讨论】:

  • 不是扫描顺序有问题吗?如果您直接在SecurityConfiguration 上指定@ComponentScan("com.highrise.isimwebapp.config.customauth") 会发生什么?
  • @MarcosBarbero 这解决了这个问题。根据您的建议,我将它直接包含在 SecurityConfiguration 中并且它有效!谢谢你。不知道其他类没有扫描到什么。但是,现在使用定义的用户名和密码成功登录后,我在 CustomAuthenticationProvider 类中遇到错误。我在尝试获取密码的那一行得到一个 NullPointerExveption:String password = authentication.getCredentials().toString();
  • 还需要在configure(HttpSecurity)方法中定义authenticationProvider
  • @MarcosBarbero 好的..你能指导一下如何做到这一点吗?因为我似乎没有在互联网上的示例中得到这部分......
  • 在你的permitAll 之后像这样.permitAll().and().authenticationProvider(authProvider).//rest of your code

标签: java spring-mvc spring-security custom-authentication beancreationexception


【解决方案1】:

问题可能出在包扫描的顺序上,我可以建议你两种方法:

  1. @ComponentScan("com.highrise.isimwebapp.config.customauth") 移至SecurityConfiguration 类。
  2. CustomAuthenticationProvider 类中删除@Component 注释,并在SecurityConfiguration 中声明@Bean,如下所示:
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(customAuthProvider());
  }

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

    http.authorizeRequests()
      .antMatchers("/resources/**").permitAll()
      .antMatchers("/icon/**").permitAll()
      .anyRequest().authenticated()
 .and().formLogin().loginPage("/login").usernameParameter("username").passwordParameter("password").permitAll().defaultSuccessUrl("/persons/listall")
    .and().csrf().disable();

  }

  @Bean
  public CustomAuthenticationProvider customAuthProvider() {
    return new CustomAuthenticationProvider();
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-20
    • 2016-03-29
    • 2011-11-11
    • 2014-09-01
    • 1970-01-01
    • 2013-12-26
    • 2015-06-20
    相关资源
    最近更新 更多