December 7, 2008

at Sunday, December 07, 2008 Labels: , , Posted by Billy

I'm currenlty working on a spring application that uses Spring Security to manage logins and page access on my site. After following the general process to set up Spring Security, as outlined in many online tutorials, you can retrieve the user information stored in the session as follows:

final SecurityContext sc = SecurityContextHolder.getContext();
final Authentication auth = sc.getAuthentication();
auth.getPrincipal();


In a typical security setup auth.getPrincipal will return a Spring Security user object which contains the current user's login name, password and roles. For my application, I wanted this object to also contain the user's unique id. This can be accomplished by extending two classes in a typical spring security setup.

In Spring Security, the authenticationDao is responsible for looking up the user's credentials. In my application the users are stored in a database, so at first I used JdbcDaoImpl for this. I wanted to return the user id as well, so this class needed some slight modifications. My new class extended JdbcDaoImpl and looks similar to this:
public class JdbcDaoUserIdImpl extends JdbcDaoImpl {

/**
* Injected by spring
*/
private UserDao userDao;

public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}

/**
* Returns a UserDetails object that also contains the user's unique id
*
* @see org.springframework.security.userdetails.jdbc.JdbcDaoImpl#createUserDetails(java.lang.String,
* org.springframework.security.userdetails.UserDetails,
* org.springframework.security.GrantedAuthority[])
*/
protected UserDetails createUserDetails(String username,
UserDetails userFromUserQuery,
GrantedAuthority[] combinedAuthorities) {
String returnUsername = userFromUserQuery.getUsername();

if (!isUsernameBasedPrimaryKey()) {
returnUsername = username;
}

User user = userDao.getUser(username);

return new UserId(user.getId(), returnUsername, userFromUserQuery
.getPassword(), userFromUserQuery.isEnabled(), true, true,
true, combinedAuthorities);
}

}


Notice that instead of returning a Spring Security User object it returns a UserId object. This class extends the User class and simply has one additional field containing, as you guessed, the user Id. It looks something like this:
public class UserId extends User {

private static final long serialVersionUID = -8275492272371421013L;
private long id;

public UserId( long id, String username, String password, boolean enabled,
boolean accountNonExpired, boolean credentialsNonExpired,
boolean accountNonLocked, GrantedAuthority[] authorities)
throws IllegalArgumentException {
super(username, password, enabled, accountNonExpired, credentialsNonExpired,
accountNonLocked, authorities);
this.id = id;
}

/**
* Sets the user's unique id in the server's session object
* @param id the user's id
*/
public void setId(long id) {
this.id = id;
}

/**
*
* @return the user's unique id
*/
public long getId() {
return this.id;
}

public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(super.toString()).append(": ");
sb.append("Id: ").append(this.id).append("; ");
return sb.toString();
}


}


After updating the security configuration files to use the new classes , we can store as many details as we like in each session. To get to the details, in your servlets cast the auth.getPrincipal object to your new class, in our case UserId.

0 comments: