Spring security Cant autowire UserDetailsS​​ervice

时间:2015-12-23 08:16:49

标签: java spring hibernate spring-mvc spring-security

我试图从数据库添加身份验证时遇到困难。

这是错误日志:

  

2015年12月23日08:24:32.819严重[localhost-startStop-1]   org.springframework.web.context.ContextLoader.initWebApplicationContext   上下文初始化失败   org.springframework.beans.factory.BeanCreationException:错误   创建名称为' securityConfig':注入自动装配的bean   依赖失败;嵌套异常是   org.springframework.beans.factory.BeanCreationException:不能   autowire字段:   org.springframework.security.core.userdetails.UserDetailsS​​ervice   kamienica.configuration.SecurityConfig.userDetailsS​​ervice;嵌套   例外是   org.springframework.beans.factory.NoSuchBeanDefinitionException:没有   合格的bean类型   [org.springframework.security.core.userdetails.UserDetailsS​​ervice]   找到依赖:预计至少有1个bean符合条件   autowire候选人这种依赖。依赖注释:   {@ org.springframework.beans.factory.annotation.Autowired(所需=真),   @ org.springframework.beans.factory.annotation.Qualifier(值= customUserDetailsS​​ervice)}       在   org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)       在   org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)       在   org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)       在   org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)       在   org.springframework.beans.factory.support.AbstractBeanFactory $ 1.getObject(AbstractBeanFactory.java:302)       在   org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)       在   org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)       在   org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)       在   org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)       在   org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)       在   org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)       在   org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)       在   org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)       在   org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)       在   org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4727)       在   org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5167)       在   org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)       在   org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725)       在   org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701)       在   org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)       在   org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:586)       在   org.apache.catalina.startup.HostConfig $ DeployDescriptor.run(HostConfig.java:1750)       在java.util.concurrent.Executors $ RunnableAdapter.call(未知   来自)java.util.concurrent.FutureTask.run(未知来源)at   java.util.concurrent.ThreadPoolExecutor.runWorker(未知来源)at   java.util.concurrent.ThreadPoolExecutor $ Worker.run(未知来源)at   java.lang.Thread.run(未知来源)引起:   org.springframework.beans.factory.BeanCreationException:不能   autowire字段:   org.springframework.security.core.userdetails.UserDetailsS​​ervice   kamienica.configuration.SecurityConfig.userDetailsS​​ervice;嵌套   例外是   org.springframework.beans.factory.NoSuchBeanDefinitionException:没有   合格的bean类型   [org.springframework.security.core.userdetails.UserDetailsS​​ervice]   找到依赖:预计至少有1个bean符合条件   autowire候选人这种依赖。依赖注释:   {@ org.springframework.beans.factory.annotation.Autowired(所需=真),   @ org.springframework.beans.factory.annotation.Qualifier(值= customUserDetailsS​​ervice)}       在   org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor $ AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)       在   org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)       在   org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)       ... 26更多引起:   org.springframework.beans.factory.NoSuchBeanDefinitionException:没有   合格的bean类型   [org.springframework.security.core.userdetails.UserDetailsS​​ervice]   找到依赖:预计至少有1个bean符合条件   autowire候选人这种依赖。依赖注释:   {@ org.springframework.beans.factory.annotation.Autowired(所需=真),   @ org.springframework.beans.factory.annotation.Qualifier(值= customUserDetailsS​​ervice)}       在   org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1103)       在   org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:963)       在   org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)       在   org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor $ AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)       ......还有28个

我的配置类:

1)AppConfig。

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "kamienica")
public class AppConfig {

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

    @Bean
    public MessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasename("messages");
        return messageSource;
    }

}

2)AppInitializer:

public class AppInitializer implements WebApplicationInitializer {

    public void onStartup(ServletContext container) throws ServletException {

        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(AppConfig.class);
        ctx.setServletContext(container);

        ServletRegistration.Dynamic servlet = container.addServlet("dispatcher", new DispatcherServlet(ctx));

        // added to handle local characters
        FilterRegistration.Dynamic fr = container.addFilter("encodingFilter", new CharacterEncodingFilter());
        fr.setInitParameter("encoding", "UTF-8");
        fr.setInitParameter("forceEncoding", "true");
        fr.addMappingForUrlPatterns(null, true, "/*");

        servlet.setLoadOnStartup(1);
        servlet.addMapping("/");

    }

}

现在是最重要的部分:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    @Qualifier("customUserDetailsService")
    UserDetailsService userDetailsService;

    //
    // @Autowired
    // CustomSuccessHandler customSuccessHandler;
    //
    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
        auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/", "/index").permitAll().antMatchers("/Admin/**")
                .access("hasRole('ADMIN')").antMatchers("/User/**").access("hasRole('ADMIN') or hasRole('USER')")
                // .and().formLogin().loginPage("/login")
                .and().formLogin()
                // .loginPage("/login")
                // .successHandler(customSuccessHandler)
                // .usernameParameter("email").passwordParameter("password")
                // .and().csrf()
                // .and().exceptionHandling().accessDeniedPage("/Access_Denied")
        ;
    }
}

我的自定义用户服务:

@Component
@Service("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    TenantService tenantService;

    @Transactional(readOnly = true)
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {

        Tenant tenant = tenantService.loadByMail(email);

        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        authorities.add(new SimpleGrantedAuthority(tenant.getRole()));
        return new org.springframework.security.core.userdetails.User(tenant.getEmail(), tenant.getPassword(), true,
                true, true, true, authorities);
    }

}

我在这里做错了什么?

编辑1。 我修改了下面文件中的注释,但没有解决问题:

@Service("userDetailsService")
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    TenantService tenantService;

    @Transactional(readOnly = true)
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {

        Tenant tenant = tenantService.loadByMail(email);

        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        authorities.add(new SimpleGrantedAuthority(tenant.getRole()));
        return new org.springframework.security.core.userdetails.User(tenant.getEmail(), tenant.getPassword(), true,
                true, true, true, authorities);
    }

}

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    UserDetailsService userDetailsService;

    //
    // @Autowired
    // CustomSuccessHandler customSuccessHandler;
    //
    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
        auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/", "/index").permitAll().antMatchers("/Admin/**")
                .access("hasRole('ADMIN')").antMatchers("/User/**").access("hasRole('ADMIN') or hasRole('USER')")
                // .and().formLogin().loginPage("/login")
                .and().formLogin()
                // .loginPage("/login")
                // .successHandler(customSuccessHandler)
                // .usernameParameter("email").passwordParameter("password")
                // .and().csrf()
                // .and().exceptionHandling().accessDeniedPage("/Access_Denied")
        ;
    }
}

编辑2:根据塞尔瓦的建议:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    CustomUserDetailsService customUserDetailsService;

    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserDetailsService);
        auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/", "/index").permitAll().antMatchers("/Admin/**")
                .access("hasRole('ADMIN')").antMatchers("/User/**").access("hasRole('ADMIN') or hasRole('USER')")
                .and().formLogin();
    }
}

不幸的是同样的结果:

  

没有类型的限定bean   找到依赖项的[kamienica.service.CustomUserDetailsS​​ervice]:   预计至少有1个豆有资格成为autowire候选人   这种依赖。依赖注释:   {@ org.springframework.beans.factory.annotation.Autowired(所需=真)}

3 个答案:

答案 0 :(得分:5)

  1. 使用@Component@ServiceCustomUserDetailsService,而不是两者。
  2. 如果您使用的是@Service,请按以下方式使用:

    @Service("userDetailsService")

  3. 现在摆脱@Qualifier。只需使用:

    @Autowired UserDetailsService userDetailsService;

答案 1 :(得分:1)

我是Spring Boot的初学者,我遇到了类似的问题,但是当我为Spring认证做测试时。 我的情况:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class DefaultUserAuthenticationTest {

@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;

@Before
public void setUp() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
                  .build();
...

并收到:

org.springframework.beans.factory.UnsatisfiedDependencyException:  创建名称为&#39; some.package.myClass.DefaultUserAuthenticationTest&#39;的bean时出错:  通过字段“webApplicationContext”表达的不满意依赖性;  嵌套异常是org.springframework.beans.factory.NoSuchBeanDefinitionException:  没有符合条件的bean&#39; org.springframework.web.context.WebApplicationContext&#39;可供选择:  预计至少有1个豆有资格成为autowire候选人。依赖注释: {@ org.springframework.beans.factory.annotation.Autowired(所需=真)}

当我这样做时:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration  //added this annotation
public class DefaultUserAuthenticationTest {

@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
...

异常消失

我找到了解决方案here

答案 2 :(得分:0)

我也面临着同样的问题,问题是我的一个安全软件包拼错了。所有软件包均为com.apps.test,出于安全考虑,该软件包为com.app.test,但失败了。 请检查所有包的初始名称,因为在组件扫描期间,如果我不同,它将失败。