无法将 UserDetailsService 自动装配到 WebSecurityConfigurerAdapter
Cannot Autowire UserDetailsService into WebSecurityConfigurerAdapter
您好,我遇到了 Autowired UsrDetailsService 的问题,我发现很多其他人也有同样的问题,但没有其他解决方案适合我(我不知道为什么)
我使用java配置(没有xml)
Error code
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'securityConfig':
Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private com.mycompany.delivery.service.AccountServiceImpl com.mycompany.delivery.config.SecurityConfig.accUserDetailsService;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.mycompany.delivery.service.AccountServiceImpl] 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=accUserDetailsService)}
当我将此 class 自动连接到 Controller 或其他任何它工作正常的地方时,其他一切都可以正常自动连接到 WebSecurityConfigurerAdapter 我不能。
我的安全配置:
Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("accUserDetailsService")
private AccountServiceImpl accUserDetailsService;
public AccountServiceImpl getAccUserDetailsService() {
return accUserDetailsService;
}
public void setAccUserDetailsService(AccountServiceImpl accUserDetailsService) {
this.accUserDetailsService = accUserDetailsService;
}
// @Override
// protected void configure(AuthenticationManagerBuilder registry) throws Exception {
// registry.userDetailsService(accUserDetailsService);
//}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("mkyong").password("123456").roles("USER");
auth.inMemoryAuthentication().withUser("admin").password("123456").roles("ADMIN");
auth.inMemoryAuthentication().withUser("dba").password("123456").roles("DBA");
}
//.csrf() is optional, enabled by default, if using WebSecurityConfigurerAdapter constructor
@Bean(name = "myAuthenticationManager")
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/admin/**").access("hasRole('ROLE_USER')")
.antMatchers("/admin/partlyVisible/**").access("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')").and()
.formLogin().loginPage("/admin/login").failureUrl("/admin/login?error")
.usernameParameter("username").passwordParameter("password")
.and()
.logout().logoutSuccessUrl("/admin/login?logout").and()
.exceptionHandling().accessDeniedPage("/admin/403")
.and()
.csrf();
}
}
我的 WebMvcConfigurerAdapter
@Configuration
@EnableWebMvc
@Import({ SecurityConfig.class })
@ComponentScan(basePackages = "com.mycompany.*")
@ImportResource({"classpath:applicationContext.xml"})
@EnableTransactionManagement
public class MySpringMvcConfig extends WebMvcConfigurerAdapter {
final static Logger log = LoggerFactory.getLogger(MySpringMvcConfig.class);
/**
* Maps the main page to a specific view.
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
log.debug("mapping URL / to home view");
registry.addViewController("/").setViewName("home");
registry.addViewController("/snoop").setViewName("snoop");
}
/**
* Enables default Tomcat servlet that serves static files.
*/
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
log.debug("enabling default servlet for static files");
configurer.enable();
}
/**
* Provides mapping from view names to JSP pages in WEB-INF/jsp directory.
*/
@Bean
public ViewResolver viewResolver() {
log.debug("registering JSP in /WEB-INF/jsp/ as views");
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
/**
* Provides localized messages.
*/
@Bean
public MessageSource messageSource() {
log.debug("registering ResourceBundle 'Texts' for messages");
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("Texts");
return messageSource;
}
/**
* Provides JSR-303 Validator.
*/
@Bean
public Validator validator() {
log.debug("validator()");
return new LocalValidatorFactoryBean();
}
}
AbstractAnnotationConfigDispatcherServletInitializer
public class MyStartInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
private Object sc;
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
//create Spring beans context configured in MySpringMvcConfig.class
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(MySpringMvcConfig.class);
ctx.register(SecurityConfig.class);
//register Spring MVC main Dispatcher servlet
ServletRegistration.Dynamic disp = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
disp.setLoadOnStartup(1);
disp.addMapping("/");
//register filter setting utf-8 encoding on all requests
FilterRegistration.Dynamic encoding = servletContext.addFilter("encoding", CharacterEncodingFilter.class);
encoding.setInitParameter("encoding", "utf-8");
encoding.addMappingForUrlPatterns(null, false, "/*");
//register bundle also for JSTL fmt: tags which are not behind DispatcherServlet
servletContext.setInitParameter(Config.FMT_LOCALIZATION_CONTEXT, "Texts");
}
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { MySpringMvcConfig.class, SecurityConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
AbstractSecurityWebApplicationInitializer
public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {
public SpringSecurityInitializer() {
super(SecurityConfig.class);
}
}
最后我的 UserDetailsService
@Service(value = "accUserDetailsService")
public class AccountServiceImpl implements UserDetailsService {
@Autowired
private AccountDAO accountDao;
public AccountDAO getAccountDao() {
return accountDao;
}
public void setAccountDao(AccountDAO accountDao) {
this.accountDao = accountDao;
}
@Override
public UserDetails loadUserByUsername(String string) throws UsernameNotFoundException {
UserDetails userDetails = null;
Account account = accountDao.getByLogin(string);
if (account == null) {
throw new UsernameNotFoundException("Account not found.");
}
userDetails = new AccountAdapter(account);
return userDetails;
}
}
感谢您的帮助
又过了一个小时,我成功了(但不确定how/why)
我的安全配置:
@Configuration
@EnableWebSecurity
改为
@Configuration
@EnableWebMvcSecurity
@ImportResource({"classpath:applicationContext.xml"})
@EnableGlobalMethodSecurity
ImportResource 很重要,但现在我有两次 importrecource,第一次在这里,第二次在 WebMvcConfigurerAdapter
如果我对这个解释有误,请纠正我。
使用@EnableWebSecurity 后,spring 不允许使用@AutoWired 然后我查看了@@EnableWebSecurity,它没有@Component 或任何Sterotype 注释所以我的结论是这样因为不允许@Autowired.
@ImportResource({"classpath:applicationContext.xml"}) 意味着你对 spring 说我需要 applicationContext 在这个 class 它基本上包含所有 bean,这就是为什么它之后没有抛出任何错误的原因。
您好,我遇到了 Autowired UsrDetailsService 的问题,我发现很多其他人也有同样的问题,但没有其他解决方案适合我(我不知道为什么) 我使用java配置(没有xml)
Error code
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'securityConfig':
Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private com.mycompany.delivery.service.AccountServiceImpl com.mycompany.delivery.config.SecurityConfig.accUserDetailsService;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.mycompany.delivery.service.AccountServiceImpl] 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=accUserDetailsService)}
当我将此 class 自动连接到 Controller 或其他任何它工作正常的地方时,其他一切都可以正常自动连接到 WebSecurityConfigurerAdapter 我不能。
我的安全配置:
Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("accUserDetailsService")
private AccountServiceImpl accUserDetailsService;
public AccountServiceImpl getAccUserDetailsService() {
return accUserDetailsService;
}
public void setAccUserDetailsService(AccountServiceImpl accUserDetailsService) {
this.accUserDetailsService = accUserDetailsService;
}
// @Override
// protected void configure(AuthenticationManagerBuilder registry) throws Exception {
// registry.userDetailsService(accUserDetailsService);
//}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("mkyong").password("123456").roles("USER");
auth.inMemoryAuthentication().withUser("admin").password("123456").roles("ADMIN");
auth.inMemoryAuthentication().withUser("dba").password("123456").roles("DBA");
}
//.csrf() is optional, enabled by default, if using WebSecurityConfigurerAdapter constructor
@Bean(name = "myAuthenticationManager")
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/admin/**").access("hasRole('ROLE_USER')")
.antMatchers("/admin/partlyVisible/**").access("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')").and()
.formLogin().loginPage("/admin/login").failureUrl("/admin/login?error")
.usernameParameter("username").passwordParameter("password")
.and()
.logout().logoutSuccessUrl("/admin/login?logout").and()
.exceptionHandling().accessDeniedPage("/admin/403")
.and()
.csrf();
}
}
我的 WebMvcConfigurerAdapter
@Configuration
@EnableWebMvc
@Import({ SecurityConfig.class })
@ComponentScan(basePackages = "com.mycompany.*")
@ImportResource({"classpath:applicationContext.xml"})
@EnableTransactionManagement
public class MySpringMvcConfig extends WebMvcConfigurerAdapter {
final static Logger log = LoggerFactory.getLogger(MySpringMvcConfig.class);
/**
* Maps the main page to a specific view.
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
log.debug("mapping URL / to home view");
registry.addViewController("/").setViewName("home");
registry.addViewController("/snoop").setViewName("snoop");
}
/**
* Enables default Tomcat servlet that serves static files.
*/
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
log.debug("enabling default servlet for static files");
configurer.enable();
}
/**
* Provides mapping from view names to JSP pages in WEB-INF/jsp directory.
*/
@Bean
public ViewResolver viewResolver() {
log.debug("registering JSP in /WEB-INF/jsp/ as views");
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
/**
* Provides localized messages.
*/
@Bean
public MessageSource messageSource() {
log.debug("registering ResourceBundle 'Texts' for messages");
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("Texts");
return messageSource;
}
/**
* Provides JSR-303 Validator.
*/
@Bean
public Validator validator() {
log.debug("validator()");
return new LocalValidatorFactoryBean();
}
}
AbstractAnnotationConfigDispatcherServletInitializer
public class MyStartInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
private Object sc;
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
//create Spring beans context configured in MySpringMvcConfig.class
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(MySpringMvcConfig.class);
ctx.register(SecurityConfig.class);
//register Spring MVC main Dispatcher servlet
ServletRegistration.Dynamic disp = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
disp.setLoadOnStartup(1);
disp.addMapping("/");
//register filter setting utf-8 encoding on all requests
FilterRegistration.Dynamic encoding = servletContext.addFilter("encoding", CharacterEncodingFilter.class);
encoding.setInitParameter("encoding", "utf-8");
encoding.addMappingForUrlPatterns(null, false, "/*");
//register bundle also for JSTL fmt: tags which are not behind DispatcherServlet
servletContext.setInitParameter(Config.FMT_LOCALIZATION_CONTEXT, "Texts");
}
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { MySpringMvcConfig.class, SecurityConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
AbstractSecurityWebApplicationInitializer
public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {
public SpringSecurityInitializer() {
super(SecurityConfig.class);
}
}
最后我的 UserDetailsService
@Service(value = "accUserDetailsService")
public class AccountServiceImpl implements UserDetailsService {
@Autowired
private AccountDAO accountDao;
public AccountDAO getAccountDao() {
return accountDao;
}
public void setAccountDao(AccountDAO accountDao) {
this.accountDao = accountDao;
}
@Override
public UserDetails loadUserByUsername(String string) throws UsernameNotFoundException {
UserDetails userDetails = null;
Account account = accountDao.getByLogin(string);
if (account == null) {
throw new UsernameNotFoundException("Account not found.");
}
userDetails = new AccountAdapter(account);
return userDetails;
}
}
感谢您的帮助
又过了一个小时,我成功了(但不确定how/why)
我的安全配置:
@Configuration
@EnableWebSecurity
改为
@Configuration
@EnableWebMvcSecurity
@ImportResource({"classpath:applicationContext.xml"})
@EnableGlobalMethodSecurity
ImportResource 很重要,但现在我有两次 importrecource,第一次在这里,第二次在 WebMvcConfigurerAdapter
如果我对这个解释有误,请纠正我。
使用@EnableWebSecurity 后,spring 不允许使用@AutoWired 然后我查看了@@EnableWebSecurity,它没有@Component 或任何Sterotype 注释所以我的结论是这样因为不允许@Autowired.
@ImportResource({"classpath:applicationContext.xml"}) 意味着你对 spring 说我需要 applicationContext 在这个 class 它基本上包含所有 bean,这就是为什么它之后没有抛出任何错误的原因。