java 自定义 UserDetailsService 似乎不是自动装配的
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35344135/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Custom UserDetailsService it seems to be not autowired
提问by DevKev
Well I've expended quite a time figuring out what the problem with my code is. According to the trace that tomcat is sending me it has something to do with a custom UserDetailsService
that I create for connecting Spring Security and JPA to make a login system based on data in a Database. I've read several articles so far talking about this issue but I haven't found a solution for my one. So heres the error trace:
好吧,我花了很长时间才弄清楚我的代码有什么问题。根据 tomcat 发送给我的跟踪,它与UserDetailsService
我为连接 Spring Security 和 JPA 以基于数据库中的数据创建登录系统而创建的自定义有关。到目前为止,我已经阅读了几篇讨论这个问题的文章,但我还没有找到适合我的解决方案。所以继承人的错误跟踪:
ERROR: org.springframework.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.springframework.security.core.userdetails.UserDetailsService com.trabajotoo.saleisi.configuration.SpringSecurityConfig.userDetailsService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.core.userdetails.UserDetailsService] 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), @org.springframework.beans.factory.annotation.Qualifier(value=customUserDetailsService)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:446)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:328)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4937)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5434)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.springframework.security.core.userdetails.UserDetailsService com.trabajotoo.saleisi.configuration.SpringSecurityConfig.userDetailsService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.core.userdetails.UserDetailsService] 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), @org.springframework.beans.factory.annotation.Qualifier(value=customUserDetailsService)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 22 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.core.userdetails.UserDetailsService] 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), @org.springframework.beans.factory.annotation.Qualifier(value=customUserDetailsService)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1119)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545)
... 24 more
Heres my CustomUserDetailsService
:
这是我的CustomUserDetailsService
:
package com.trabajotoo.saleisi.services;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import com.trabajotoo.saleisi.model.RolAsignado;
import com.trabajotoo.saleisi.model.Usuario;
@Service("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UsuarioService userService;
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String userName) throws
UsernameNotFoundException {
Usuario user = userService.findByUsername(userName);
if (user == null){
System.out.println("User not found");
throw new UsernameNotFoundException("Username not found");
}
return new User(user.getNomUsuario(), user.getPassword(), user.isEstado(),
true, true, true, getGrantedAuthorities(user));
}
private List<GrantedAuthority> getGrantedAuthorities(Usuario user){
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for(RolAsignado rolAsign: user.getRolesAsignados()){
if (rolAsign.isEstado()){
authorities.add(new SimpleGrantedAuthority("ROLE_"+
rolAsign.getRol().getCodigo()));
break;
}
}
return authorities;
}
}
and here is my SprinSecurityConfig
class:
这是我的SprinSecurityConfig
课:
package com.trabajotoo.saleisi.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import com.trabajotoo.saleisi.services.CustomSuccessHandler;
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
@Qualifier("customUserDetailsService")
UserDetailsService userDetailsService;
@Autowired
CustomSuccessHandler customSuccesHandler;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
@Override
protected void configure(HttpSecurity http) throws Exception{
http.authorizeRequests()
.antMatchers("/register").permitAll()
.antMatchers("/admin/**").access("hasRole('ADMIN')")
.antMatchers("/coordinador/**").access("hasRole('COORD')")
.antMatchers("/director/**").access("hasRole('DIR')")
.and().formLogin().loginPage("/").permitAll()
.successHandler(customSuccesHandler).usernameParameter("nomUsuario")
.passwordParameter("password");
}
}
Here's my SpringSecurityWebApplicationInitializer
:
这是我的SpringSecurityWebApplicationInitializer
:
package com.trabajotoo.saleisi.configuration;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityWebApplicationInitializer extends
AbstractSecurityWebApplicationInitializer{
}
My WebConfiguration
class:
我的WebConfiguration
班级:
package com.trabajotoo.saleisi.configuration;
import javax.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
@Configuration
@EnableWebMvc
@Import({HibernateConfig.class})
@ComponentScan({"com.trabajotoo.saleisi.controllers", "com.trabajotoo.saleisi.dao",
"com.trabajotoo.saleisi.services"})
public class WebConfiguration extends WebMvcConfigurerAdapter{
@Resource
private Environment env;
// Configuracion de los archivos css,js,etc.
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry){
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
// Configuracion del manejo de las vistas
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
and My WebAppInitializer
:
和我的WebAppInitializer
:
package com.trabajotoo.saleisi.configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import com.trabajotoo.saleisi.configuration.RootContext;
import com.trabajotoo.saleisi.configuration.WebConfiguration;
public class ApplicationInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { RootContext.class, SpringSecurityConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebConfiguration.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
By the way I'm using Spring Security 4.0.3 and Spring MVC 4.2.4
顺便说一下,我使用的是 Spring Security 4.0.3 和 Spring MVC 4.2.4
回答by Rajesh
Try adding below in WebSecurityConfiguration.java
尝试在 WebSecurityConfiguration.java 中添加以下内容
@Bean
public UserDetailsService userDetailsService() {
return super.userDetailsService();
}
回答by Ali Dehghani
You're the victim of Application Context Hierarchies. Your CustomUserDetailsService
is picked up by WebConfiguration
component scanning and defined in this context, since:
您是Application Context Hierarchies的受害者。您CustomUserDetailsService
被WebConfiguration
组件扫描选中并在此上下文中定义,因为:
@ComponentScan({"com.trabajotoo.saleisi.controllers", "com.trabajotoo.saleisi.dao",
"com.trabajotoo.saleisi.services"})
public class WebConfiguration extends WebMvcConfigurerAdapter { ... }
Then you're gonna inject this bean into SpringSecurityConfig
, which is WebConfiguration
's parent context. Since SpringSecurityConfig
can not access to the beans defined in its child context, it will throw a NoSuchBeanDefinitionException
.
然后你要把这个 bean 注入SpringSecurityConfig
,它是WebConfiguration
的父上下文。由于SpringSecurityConfig
无法访问在其子上下文中定义的 bean,它将抛出一个NoSuchBeanDefinitionException
.
In order to solve this problem, you should define CustomUserDetailsService
in root context. I'm not quite familiar with your project structure but scanning components in the service layer by RootContext
or SpringSecurityConfig
may fix your problem. Something like this:
为了解决这个问题,你应该CustomUserDetailsService
在根上下文中定义。我不太熟悉您的项目结构,但扫描服务层中的组件RootContext
或SpringSecurityConfig
可能会解决您的问题。像这样的东西:
@Configuration
@ComponentScan("com.trabajotoo.saleisi.services")
public class RooContext { ... }