Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security Java - Multiple Authentication Manager - 2 bean found error

I have 2 authentication manager in my application.

@Configuration
@EnableWebMvcSecurity
@ComponentScan
@ImportResource("classpath:security-context.xml")
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private AuthenticationEntryPoint webAuthenticationEntryPoint = null;

    private AuthenticationManager webAuthenticationManager = null;

    private final webPreAuthenticatedProcessingFilter webPreAuthenticatedProcessingFilter;


    public WebSecurityConfig() {
        super();
        webPreAuthenticatedProcessingFilter = new webPreAuthenticatedProcessingFilter();
        webPreAuthenticatedProcessingFilter.setAuthenticationManager(webAuthenticationManager);
        webPreAuthenticatedProcessingFilter.setInvalidateSessionOnPrincipalChange(true);
        webPreAuthenticatedProcessingFilter.setContinueFilterChainOnUnsuccessfulAuthentication(Boolean.FALSE);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()
            .antMatchers("/login", "/logoffUser", "/sessionExpired", "/error").permitAll()
            .anyRequest().authenticated().and().rememberMe().and().httpBasic()
            .authenticationEntryPoint(webAuthenticationEntryPoint).and()
            .addFilterAfter(webPreAuthenticatedProcessingFilter, webPreAuthenticatedProcessingFilter.class).csrf()
            .disable().logout().deleteCookies("JSESSIONID").logoutSuccessUrl("/logoff").invalidateHttpSession(true);
    }

    @Autowired
    @Qualifier("webAuthManager")
    public void setwebAuthenticationManager(AuthenticationManager webAuthenticationManager) {

        this.webAuthenticationManager = webAuthenticationManager;
        webPreAuthenticatedProcessingFilter.setAuthenticationManager(this.webAuthenticationManager);
    }

    @Autowired
    public void setwebAuthenticationEntryPoint(AuthenticationEntryPoint webAuthenticationEntryPoint) {

        this.webAuthenticationEntryPoint = webAuthenticationEntryPoint;
    }

}

PreAuthenticatedFilter class,

@Component("preAuthenticatedFilter")
public class WebPreAuthenticatedProcessingFilter extends AbstractPreAuthenticatedProcessingFilter {   
    @Override
    @Autowired
    @Qualifier("webAuthManager")
    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
        super.setAuthenticationManager(authenticationManager);
    }
}

WebAuthenticationManager class,

@Service
@ComponentScan
@Component("webAuthManager")
public class WebAuthenticationManager implements AuthenticationManager {


    @Override
    public Authentication authenticate(Authentication authentication) {

       // ...

    }
}

And the xml file which has one more authnetication manager,

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security 
                        http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <bean id="ldapConfig" class="com.wellmanage.mnpi.core.jms.LdapConfig">
        <constructor-arg name="user" value="${ldap.conn.user}"/>
        <constructor-arg name="sid" value="${ldap.conn.sid}"/>
    </bean>

    <security:ldap-server url="${ldap.url}" 
        manager-dn="${ldap.conn.user}" manager-password="#{ldapConfig.getPassword()}" />

    <security:authentication-manager alias="ldapAuthManager" id="ldapAuthManager">
        <security:ldap-authentication-provider
            user-search-filter="(&amp;(sAMAccountName={0})(objectclass=organizationalPerson))"
            user-search-base="OU=${ldap.user-search-base.name}"
            group-search-filter="(member={0})" group-search-base="OU=Global-Groups"
            group-role-attribute="cn"/>
    </security:authentication-manager>

    <bean id="mq.accessDecisionManager"
        class="org.springframework.security.access.vote.AffirmativeBased">
        <constructor-arg>
            <list>
                <bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter"/>
            </list>
        </constructor-arg>
    </bean>
</beans>

Even I use the Qualifier, I get the below exception.

Exception in thread "main" org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:133)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:474)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
    at com.wellmanage.mnpi.Application.main(Application.java:60)
Caused by: org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat
    at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:98)
    at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.<init>(TomcatEmbeddedServletContainer.java:75)
    at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getTomcatEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:378)
    at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:155)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:157)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:130)
    ... 5 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is java.lang.IllegalArgumentException: Expecting to only find a single bean for type interface org.springframework.security.authentication.AuthenticationManager, but found [webAuthManager, ldapAuthManager]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1119)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1014)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.boot.context.embedded.ServletContextInitializerBeans.getOrderedBeansOfType(ServletContextInitializerBeans.java:209)
    at org.springframework.boot.context.embedded.ServletContextInitializerBeans.addAsRegistrationBean(ServletContextInitializerBeans.java:165)
    at org.springframework.boot.context.embedded.ServletContextInitializerBeans.addAsRegistrationBean(ServletContextInitializerBeans.java:160)
    at org.springframework.boot.context.embedded.ServletContextInitializerBeans.addAdaptableBeans(ServletContextInitializerBeans.java:143)
    at org.springframework.boot.context.embedded.ServletContextInitializerBeans.<init>(ServletContextInitializerBeans.java:74)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getServletContextInitializerBeans(EmbeddedWebApplicationContext.java:234)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.selfInitialize(EmbeddedWebApplicationContext.java:221)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.access$000(EmbeddedWebApplicationContext.java:84)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext$1.onStartup(EmbeddedWebApplicationContext.java:206)
    at org.springframework.boot.context.embedded.tomcat.TomcatStarter.onStartup(TomcatStarter.java:54)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5156)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1399)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is java.lang.IllegalArgumentException: Expecting to only find a single bean for type interface org.springframework.security.authentication.AuthenticationManager, but found [webAuthManager, ldapAuthManager]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
    ... 26 more
Caused by: java.lang.IllegalArgumentException: Expecting to only find a single bean for type interface org.springframework.security.authentication.AuthenticationManager, but found [webAuthManager, ldapAuthManager]
    at org.springframework.util.Assert.isTrue(Assert.java:65)
    at org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration.lazyBean(AuthenticationConfiguration.java:112)
    at org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration.getAuthenticationMangerBean(AuthenticationConfiguration.java:122)
    at org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration.getAuthenticationManager(AuthenticationConfiguration.java:81)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.authenticationManager(WebSecurityConfigurerAdapter.java:236)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.getHttp(WebSecurityConfigurerAdapter.java:178)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.init(WebSecurityConfigurerAdapter.java:283)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.init(WebSecurityConfigurerAdapter.java:68)
    at com.wellmanage.mnpi.security.WebSecurityConfig$$EnhancerBySpringCGLIB$$c6c13351.init(<generated>)
    at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.init(AbstractConfiguredSecurityBuilder.java:367)
    at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.doBuild(AbstractConfiguredSecurityBuilder.java:320)
    at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:39)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration.springSecurityFilterChain(WebSecurityConfiguration.java:98)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$eb0d5df1.CGLIB$springSecurityFilterChain$3(<generated>)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$eb0d5df1$$FastClassBySpringCGLIB$$622492d6.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:309)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$eb0d5df1.springSecurityFilterChain(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
    ... 27 more
like image 944
user1578872 Avatar asked Aug 19 '15 21:08

user1578872


2 Answers

You need to setup 2 Providers, one for Ldap and one for Web. AuthenticationManager (if it's ProviderManager instance) will select corresponding Provider for authentication. Manager basically manages list of Providers, that do actual job.

Like (I guess its easier to configure everything in one place?):

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth  // you have to prepare following beans also
        .authenticationProvider(getLdapAuthenticationProvider())
        .authenticationProvider(getWebAuthenticationProvider());
}

See http://docs.spring.io/spring-security/site/docs/4.0.2.RELEASE/reference/htmlsingle/#core-services-authentication-manager

like image 193
Igor Artamonov Avatar answered Nov 16 '22 00:11

Igor Artamonov


Solution for XML base: If you required more than 1 authentication manager then you can define it but got warning "overriding globally registered authenticationmanager" that's mean all Element : HTTP are match with last defined authenticationmanager.

So you can try this for XML base and security v4.0+ required.

Solution: You must use "Id" attribute in authenticationmanager and same id define in "HTTP" element in "authentication-manager-ref" attribute. So then security fetch suitable authenticationmanager for particular HTTP request.

Sample code:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.0.xsd">

<!--  HTTP basic authentication for Rest API when match url pattern="/api/**"    -->

<security:http realm="API" pattern="/api/**"
    use-expressions="true" auto-config="true" create-session="stateless"
    authentication-manager-ref="APIAuthenticationManager">

    <security:intercept-url pattern="/**" access="hasRole('USER')" />
    <security:http-basic />
    <security:csrf disabled="true" />
</security:http>

<security:authentication-manager id="APIAuthenticationManager"
    alias="APIAuthenticationManager">
    <security:authentication-provider user-service-ref="APIAuthenticationProvider" />
</security:authentication-manager> 

<bean class="com.example.security.api.APIAuthentication"
    id="APIAuthenticationProvider">
</bean>


<!-- From Login authentication for web portal when match url parrern ="/web/**"    -->


<security:http realm="WEB" auto-config="true"
    use-expressions="true" create-session="always"
    authentication-manager-ref="userAuthenticationManager">

    <security:intercept-url pattern="/resources/**" access="permitAll" />
    <security:intercept-url pattern="/web/login" access="hasRole('ROLE_ANONYMOUS')" />
    <security:intercept-url pattern="/web/dashboard**" access="hasRole('USER')" method="GET" />


    <!-- Set login, landing page, Successful, unsuccessful ... -->
    <security:form-login login-page="/web/login"
        default-target-url="/web/dashboard" 
        login-processing-url="/web/dashboard"
        always-use-default-target="true"

        authentication-failure-url="/web/login?error" 
        username-parameter="email"           
        password-parameter="encryptedPassword" />

    <!-- Set logout detail -->
    <security:logout logout-url="/web/logout"
        logout-success-url="/index.jsp" 
        delete-cookies="JSESSIONID"
        invalidate-session="true" />

    <security:csrf/>
</security:http>

<security:authentication-manager id="userAuthenticationManager" alias="userAuthenticationManager">
    <security:authentication-provider user-service-ref="userAuthenticationProvider" />
</security:authentication-manager>

<bean class="com.example.security.web.UserAuthentication"
    id="userAuthenticationProvider">

</bean>    

like image 36
PratikShah Avatar answered Nov 16 '22 00:11

PratikShah