2016-04-21 2284 views
1

我對Spring Security有這個問題。如何將自定義的DaoAuthenticationProvider加載到Spring上下文中?

我有一個SecurityConfig類的java-config實現,它擴展了WebSecurityConfigurerAdapter。

在這個類我想覆蓋的方法「配置()」

@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); 
    } 

    //... 

} 

一切都OK和它的作品。

問題是「MyDaoAuthenticationProvider」組件未在Spring上下文中加載。 所以我不能在這個類注入或自動裝配任何組件:

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 
    } 

} 

這是的AuthenticationHandler類:

@Component 
public class AuthenticationHandler { 

    public void authenticate (Authentication authentication) { 
     // do stuff 
    } 

} 

如果我把@Component上MyDaoAuthenticationProvider類,我添加@自動裝配Autowired註解在SecurityConfig類:

@Autowired 
MyDaoAuthenticationProvider provider; 

上的啓動與此錯誤的應用程序崩潰:

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$1.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 

我該怎麼辦才能解決此問題? 謝謝。

編輯

SOLUTION

感謝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()); 
} 

利用這種結構,豆是正確的初始化,有沒有更多的錯誤「java.lang.IllegalArgumentException:必須設置UserDetailsS​​ervice」。

此外,bean被加載到Spring上下文中,所以DaoAuthenticationProvider中的所有注入組件都被正確解析。

回答

2

Error creating bean with name 'myDaoAuthenticationProvider' [...] A UserDetailsService must be set

MyDaoAuthenticationProvider沒有UserDetailsService。 您必須執行,注入和/或設置一個。

如果你不認爲你需要一個,那麼你可能不應該實施DaoAuthenticationProvider。也許你實際上想要實現一個通用的AuthenticationProvider,或者使用其他實現類。

例如,不使用@Component

@Bean 
public MyDaoAuthenticationProvider myAuthProvider() { 
    MyDaoAuthenticationProvider provider = new MyDaoAuthenticationProvider(); 
    provider.setPasswordEncoder(passwordEncoder()); 
    provider.setUserDetailsService(securityService); 
    return provider; 
} 

然後,您需要停止創造一個又一個在configure方法。

+0

不,我擁有它!我給他設置了這個:provider.setUserDetailsS​​ervice(securityService); –

+0

但是,如果「configure」方法尚未執行,Spring似乎無法創建一個bean。 –

+0

當您調用'new MyDaoAuthenticationProvider()'時,您可以在代碼中使用它。如果你想讓它成爲'@ Component' bean,那麼你需要以不同的方式做。 – OrangeDog

相關問題