spring-securityuserdetailsservice

How implement UserDetailsService for several types of users?


In my web app when I have one type of user (typical_user) I do the following:

1) Implement UserDetailsService

public class UserServiceImpl implements UserService, UserDetailsService {
private UserDao userDao;
@Override
public UserDetails loadUserByUsername(String username)
        throws UsernameNotFoundException
{
    UserEntity user = userDao.loadUserByEmail(username);

    if (user == null) {
        throw new UsernameNotFoundException(String.format(
                getMessageBundle().getString("badCredentials"), username));
    }

    Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
    authorities.add(new SimpleGrantedAuthority("ROLE_USER"));

    User userDetails = new User(user.getEmail(), user.getPassword(),
            authorities);

    return userDetails;
}}

2) Write configuration for that user in security-config.xml like this:

<security:authentication-manager>
    <security:authentication-provider
        user-service-ref="userService">
        <security:password-encoder hash="md5" />
    </security:authentication-provider>
</security:authentication-manager>

<bean id="daoAuthenticationProvider"
    class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
    <property name="userDetailsService" ref="userService" />
    <property name="hideUserNotFoundExceptions" value="false" />
</bean>

But now I want to have another type of user (admin). So, I need another implementation of loadUserByUsername method (where user will get ROLE_ADMIN).
I can write another class (AdminServiceImpl) but how my security-config.xml will look like??


Solution

  • As suggested, switch to database storage. Assuming you're using an ORM for DB management:

    public class Role implements org.springframework.security.core.GrantedAuthority {
        // implements what must be implemented
    }
    
    public class User implements org.springframework.security.core.userdetails.UserDetails {
    
        // your stuff...
    
        @ManyToMany(fetch = FetchType.EAGER) // shouldn't be a problem here to fetch eagerly
        private Collection<Role> roles = new HashSet<Role>();
    
        // add getters and setters
    
        /**
         * @see org.springframework.security.core.userdetails.UserDetails#getAuthorities()
         */
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return getRoles();
        }
    
    }
    
    public class UserDetailsServiceImpl implements
        org.springframework.security.core.userdetails.UserDetailsService {
    
        @Override
        public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException {
            // Load the user from your database. The ORM will take care of loading his Role collection.
        }
    
    }