java 如何将自定义 DaoAuthenticationProvider 加载到 Spring Context 中?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36775663/
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
How to load a custom DaoAuthenticationProvider into the Spring Context?
提问by Alessandro C
I have this issue with Spring Security.
我对 Spring Security 有这个问题。
I have a java-config implementation with a SecurityConfig class, that extends WebSecurityConfigurerAdapter.
我有一个带有 SecurityConfig 类的 java-config 实现,它扩展了 WebSecurityConfigurerAdapter。
In this class I want to override the method "configure()"
在这个类中,我想覆盖方法“configure()”
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, proxyTargetClass = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
MyDaoAuthenticationProvider provider = new MyDaoAuthenticationProvider();
provider.setPasswordEncoder(passwordEncoder());
provider.setUserDetailsService(securityService);
auth.authenticationProvider(provider);
}
//...
}
All is OK and it works.
一切正常,并且有效。
The problem is that "MyDaoAuthenticationProvider" component is not loaded on the Spring Context. So I can't inject or Autowired any components in this class:
问题是“MyDaoAuthenticationProvider”组件没有加载到 Spring Context 上。所以我不能在这个类中注入或自动装配任何组件:
public class MyDaoAuthenticationProvider extends DaoAuthenticationProvider {
@Autowired
AuthenticationHandler authenticationHandler; // <- authenticationHandler is null, is not resolved
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
authenticationHandler.authenticate(authentication); // <- NullPointerException in this point
}
}
This is the AuthenticationHandler class:
这是 AuthenticationHandler 类:
@Component
public class AuthenticationHandler {
public void authenticate (Authentication authentication) {
// do stuff
}
}
If I put the @Component on the MyDaoAuthenticationProvider class and I add the @Autowired annotation in the SecurityConfig class:
如果我将 @Component 放在 MyDaoAuthenticationProvider 类上并在 SecurityConfig 类中添加 @Autowired 注释:
@Autowired
MyDaoAuthenticationProvider provider;
the application crash on the start with this error:
应用程序在开始时崩溃并出现此错误:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myDaoAuthenticationProvider' defined in file [...\MyDaoAuthenticationProvider.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: A UserDetailsService must be set
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
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:4812)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5255)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalArgumentException: A UserDetailsService must be set
at org.springframework.util.Assert.notNull(Assert.java:115)
at org.springframework.security.authentication.dao.DaoAuthenticationProvider.doAfterPropertiesSet(DaoAuthenticationProvider.java:105)
at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.afterPropertiesSet(AbstractUserDetailsAuthenticationProvider.java:122)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
... 21 more
What I have to do to resolve this issue? Thanks.
我该怎么做才能解决这个问题?谢谢。
EDIT
编辑
SOLUTION
解决方案
Thanks to OrangeDog, I fixed the problem with this implementation:
感谢 OrangeDog,我解决了这个实现的问题:
@Bean
public MyDaoAuthenticationProvider myAuthProvider() throws Exception {
MyDaoAuthenticationProvider provider = new MyDaoAuthenticationProvider();
provider.setPasswordEncoder(passwordEncoder());
provider.setUserDetailsService(securityService);
return provider;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(myAuthProvider());
}
With this configuration, the bean is correctly initialized and there's no more the error "java.lang.IllegalArgumentException: A UserDetailsService must be set".
使用此配置,bean 已正确初始化,并且不再出现错误“java.lang.IllegalArgumentException: A UserDetailsService must be set”。
Furthermore, the bean is loaded into the Spring Context, so all the injected components in the DaoAuthenticationProvider are correctly resolved.
此外,bean 被加载到 Spring Context 中,因此 DaoAuthenticationProvider 中所有注入的组件都被正确解析。
回答by OrangeDog
Error creating bean with name 'myDaoAuthenticationProvider' [...] A UserDetailsService must be set
创建名为“myDaoAuthenticationProvider”的 bean 时出错 [...] 必须设置 UserDetailsService
Your MyDaoAuthenticationProvider
doesn't have a UserDetailsService
.
You must implement, inject, and/or set one. For example, without using @Component
:
你MyDaoAuthenticationProvider
没有UserDetailsService
. 您必须实现、注入和/或设置一个。例如,不使用@Component
:
@Bean
public MyDaoAuthenticationProvider myAuthProvider() {
MyDaoAuthenticationProvider provider = new MyDaoAuthenticationProvider();
provider.setPasswordEncoder(passwordEncoder());
provider.setUserDetailsService(securityService);
return provider;
}
You then need to stop creating another one in your configure
method.
然后您需要停止在您的configure
方法中创建另一个。
If you don't think that you need one, then you probably shouldn't be implementing a DaoAuthenticationProvider
. Perhaps you actually want to implement a generic AuthenticationProvider
, or use of its other implementing classes.
如果您认为不需要一个,那么您可能不应该实现DaoAuthenticationProvider
. 也许你真的想实现一个泛型AuthenticationProvider
,或者使用它的其他实现类。