Pages

Saturday, July 24, 2010

Spring Security - use custom DB schema to store user's credentials and authorities to perform authentication

Problem:
How to perform Spring Security user's authentication and not use default DB schema to store user's credentials and authorities.

Recipe:
Default Spring Security JdbcDaoImpl retrieves user details (username, password, authorities) from database with assumed schema with tables users and authorities:

Users table columns names:
- username
- password
- enabled

Authorities: table column names:
- username
- authority

Often happens that users information, authorities, access control rules are stored with using different schema or it should be fetched other way than JDBC, for example through ORM tool, like hibernate. To retrieve users data required by Spring Security from custom DB schema, we can modify Spring's JdbcDaoImpl according to our requirements:
public class UserDetailsServiceImpl extends JdbcDaoImpl {

    private UserDao userDao;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
        pl.lmoren.spring.domain.User user = userDao.findUserbyLoginName(username);
        if (user != null) {

            Collection authorities = new ArrayList();
            authorities.add(new GrantedAuthorityImpl("ROLE_USER"));

            return new AuthenticatedUserDetails(user.getEmail(), user.getName(), user.getLogin(), user.getPassword(), true, true, true, true,
                    authorities);
        }

        throw new UsernameNotFoundException(
                messages.getMessage("JdbcDaoImpl.notFound", new Object[]{username}, "Username {0} not found"), username);
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
Above class retrieve users data using userDao object - a Data Access Object that allows to query DB.

Customized Spring's user just contains new field, email address, which is later used by application logic:
public class AuthenticatedUserDetails extends User {
    private String email;

    public AuthenticatedUserDetails(String email, String name, String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection authorities) {
        super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
        this.user = user;
        this.name = name;
    }
}
AuthenticatedUserDetails class extends default Spring Security UserDetails implementation and it can contains additional details about authenticating user like: email, id, etc..
If user is found in database, in default his role is assigned to ROLE_USER. There is only one role foreseen.
If you need to retrieve authorities from database as well just override:.
  
protected List loadUserAuthorities(String username)
similar way to presented loadUserByUsername method.

And finally spring beans confiuration:



      
    
    
      
      
    
        
    


    
        
    
 
    
        
        
    
 

    
        
        
    
 
  
        
        
        
        
    


Authentication manager has reference to authentication-provider.DaoAuthenticationProvider is used to retrieve user details from an UserDetailsService. UserDetailsService is an interface that have to be implemented by classes that retrieves users specific data.
JdbcDaoImpl does that, so UserDetailsServiceImpl does as well. UserDetailsServiceImpl requires set property dataSource which defines db connection and userDao through which we want to retrieve users details. Even dataSource is not used in this example it is required by JdbcDaoImpl.

No comments:

Post a Comment