javablogspot

Just another WordPress.com weblog

[Spring Security] – Implementing Custom UserDetails using Hibernate

Posted by damuchinni on February 18, 2009

Recently was experimenting with creating a Custom UserDetails in Spring Security. Unfortunately, it took me a while before I could implement. In this post shall share my experience and how I developed it.

Assumption

I shall concentrate only on the configuration of UserDetails service. To see it in Action, you can take Spring petclinic tutorial and add the configuration to it.

Let’s briefly lay down the steps needed to implement a Custom UserDetails

Implement a Custom User Class that implements UserDetails interface (This class can be customized to fit your needs)
Implement Custom UserDetailsService to based on Hibernate
Configuring in the Spring context
Implementing Custom UserDetails

For simplicity perspective, I shall be omitting Hibernate related configuration from this section

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.userdetails.UserDetails;

public class CustomUser implements Serializable, UserDetails {
private static final long serialVersionUID = 1L;
private long id;
private String password;
private String username;
private Set roles;

public CustomUser() {
}

public Set getRoles() {
return roles;
}

public void setRoles(Set roles) {
this.roles = roles;
}

private boolean accountNonExpired;
private boolean accountNonLocked;
private boolean credentialsNonExpired;
private boolean enabled;

public GrantedAuthority[] getAuthorities() {
List list = new ArrayList();
for (Authority role : roles) {
list.add(new GrantedAuthorityImpl(role.getAuthority()));
}
return (GrantedAuthority[])list.toArray(new GrantedAuthority[0]);
}
}
Take a special note of getAuthorities(). This function from UserDetails interface needs to return all the authorities for the given user. You can store Roles in whichever format you desire, and can translate them here. For simplicity sake, here is my Authorities class.

public class Authority implements Serializable {
private static final long serialVersionUID = 1L;
private long id;
private String username;
private String authority;
}Implementing Custom UserDetailsService

Here using spring comes very handy. We extend HibernateDaoSupport and get most of the desired Hibernate functionality. Lets take a look at the class.

import java.util.List;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;

public class HibernateUserDetailsService extends HibernateDaoSupport implements UserDetailsService {
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
List results = getHibernateTemplate().find(“from CustomUser where username = ?”,
new Object[] {username});

if(results.size() < 1) {
throw new UsernameNotFoundException(username + “not found”);
}
return (UserDetails) results.get(0);
}
}Well, its that simple. We just implement loadUserByUsername(String username) function and inside that we query for the specified user using the HibernateTemplate

Configuration

It’s time to tell Spring Security to use our custom UserDetails and UserDetailsService. Ensure that petclinic application is using Hibernate Context file (applicationContext-hibernate.xml). Check the same in web.xml. Let’s take a look at what’s the configuration we need to do



Add the bean definition and update the authentication-provider configuration to use our UserDetailsservice. Restart and Spring Security shall use our Custom UserDetails.

Troubleshooting

It took me a while before I could implement this, and though of sharing the mistakes, so that you don’t repeat them

• Test User/Authority Hibernate class in isolation – I did it initially and my test suite was not complete as to detect that all the authorities were being set for the user. This let me to dig into the Spring Security code, add traces and realizing that it’s my mistake.

• Ensure that you maintain roles with a prefix ROLE_ (case-sensitive). If you choose otherwise, you have to set the prefix as desired for authorization.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s