0

I am working on a Spring-MVC application with spring-security and I have 2 different types of users who can login, one is from a personal account, and one is the group account. So basically I want 2 daoAuthenticationMethods. For both I have implemented the UserDetails and userDetailsService interface. After referring to the post on this I am trying to implement that approach. The error I am getting is conflicting userDetailsService in the Service layer. I know I cannot use 2 userDetailsService, but if I put something else in the xml's property tab, I get unknown property error. Kindly check the configuration and please tell me what I might be doing wrong.

Error log :

Offending resource: ServletContext resource [/WEB-INF/spring/appServlet/security-applicationContext.xml]; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from ServletContext resource [/WEB-INF/spring/appServlet/servlet-context.xml]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'userDetailsService' for bean class [com.journaldev.spring.service.GroupLoginServiceImpl] conflicts with existing, non-compatible bean definition of same name and class [com.journaldev.spring.service.LoginServiceImpl]
    at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:70)
    at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85)

Security-application-context.xml :

<!-- Global Security settings -->
<security:global-method-security pre-post-annotations="enabled" />
<security:http create-session="ifRequired" use-expressions="true" auto-config="true" disable-url-rewriting="true">
    <security:form-login login-page="/" default-target-url="/canvas/list"
                         always-use-default-target="false"  authentication-failure-url="/denied.jsp" />

<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
    <security:filter-chain-map path-type="ant">
        <security:filter-chain pattern="/**" filters="authenticationProcessingFilterForPersonal, authenticationProcessingFilterForGroup"/>
    </security:filter-chain-map>
</bean>

<bean id="authenticationProcessingFilterForPersonal"
      class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
    <property name="authenticationManager" ref="authenticationManagerForPersonal"/>
    <property name="filterProcessesUrl" value="/j_spring_security_check_for_person" />

</bean>

<bean id="authenticationProcessingFilterForGroup"
      class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
    <property name="authenticationManager" ref="authenticationManagerForGroup"/>
    <property name="filterProcessesUrl" value="/j_spring_security_check_for_group"/>
</bean>


<bean id="authenticationManagerForPersonal" class="org.springframework.security.authentication.ProviderManager">

<property name="providers">
        <list>
            <bean class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
                <property name="userDetailsService">
                    <ref bean="LoginServiceImpl"/>
                </property>
                <property name="passwordEncoder" ref="encoder"/>
            </bean>
        </list>
    </property>
</bean>

<bean id="authenticationManagerForGroup" class="org.springframework.security.authentication.ProviderManager">
    <property name="providers">
        <list>
            <bean class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
                <property name="userDetailsService">
                    <ref bean="GroupLoginServiceImpl"/>
                </property>
                <property name="passwordEncoder" ref="encoder"/>
            </bean>
        </list>
    </property>
</bean>


<security:authentication-manager alias="authenticationManager">
    <security:authentication-provider ref="authenticationManagerForPersonal"/>
    <security:authentication-provider ref="authenticationManagerForGroup"/>
</security:authentication-manager>

<beans:bean id="encoder"
            class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
    <beans:constructor-arg name="strength" value="11" />
</beans:bean>

LoginServiceImpl :

// This method is for the personalAccount
@Transactional
@Service("userDetailsService")
public class LoginServiceImpl implements UserDetailsService{

    @Autowired private PersonDAO personDAO;
    @Autowired private Assembler assembler;

    private static final GrantedAuthority USER_AUTH = new SimpleGrantedAuthority("ROLE_USER");

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException,DataAccessException {
        Person person = personDAO.findPersonByUsername(username.toLowerCase());
            if(person == null) { throw new UsernameNotFoundException("Wrong username or password");} 
        return assembler.buildUserFromUserEntity(person);
    }
}

GroupLoginServiceImpl :

@Transactional
@Service("userDetailsService")  // I cannot change this, it throws me error when I change this or remove this
public class GroupLoginServiceImpl implements UserDetailsService {

    @Autowired
    private GroupMembersDAO groupMembersDAO;

    @Autowired
    private GroupAssembler groupAssembler;

    private static final GrantedAuthority USER_AUTH = new SimpleGrantedAuthority("ROLE_GROUP");

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException,DataAccessException {
        GroupMembers groupMembers = groupMembersDAO.findMemberByUsername(username.toLowerCase());
        if(groupMembers == null) { throw new UsernameNotFoundException("Wrong username or password");} 
        return groupAssembler.buildUserFromUserEntity(groupMembers);
    }
}

I can post any other methods too if necessary. kindly let me know what to do. Any pointers are welcome. Thank you.

Community
  • 1
  • 1
We are Borg
  • 5,117
  • 17
  • 102
  • 225

1 Answers1

1

I think you have misunderstood how to write the XML. The first instance should be something like:

<property name="userDetailsService" ref="userDetailsService">

And the second:

<property name="userDetailsService" ref="groupDetailsService">
holmis83
  • 15,922
  • 5
  • 82
  • 83
  • I had already tried what you had said, the error log is in the main post with the changes you suggested. I added the groupDetailsService in the GroupServiceLoginImpl too. Kindly have a look. – We are Borg Jan 19 '15 at 15:58
  • @WeareBorg Different problem, you have three authentication managers! Cleanup. – holmis83 Jan 19 '15 at 16:35
  • I only have one global authenticationManager, the others are just beans. – We are Borg Jan 19 '15 at 16:47
  • @WeareBorg The security namespace is shorthand for defining beans. Hence, authentication-manager element = authentication manager bean. – holmis83 Jan 19 '15 at 18:22
  • Ok, when you say that, I did tried removing the block of code with and the authenticationProvider under it. When I do that, I get an error No bean named 'org.springframework.security.authenticationManager' is defined ?? Can you help me with some clarification what I have to change in security-application-context.xml. Thank you. – We are Borg Jan 20 '15 at 08:08
  • @WeareBorg I have never applied multiple authentication managers, but maybe a missing `authentication-manager-ref`? – holmis83 Jan 20 '15 at 14:51
  • I have never used a authentication-manager-ref..I have added a new thread depending upon modifications suggested, can you please check http://stackoverflow.com/questions/28041310/error-creating-bean-with-name-authenticationmanager . Thank you very much. Most of the task I am trying to do is referred from http://stackoverflow.com/questions/4783063/configuring-spring-security-3-x-to-have-multiple-entry-points . let me know if you need any more information. Thanks a lot. – We are Borg Jan 20 '15 at 14:56