Showing posts with label Spring. Show all posts
Showing posts with label Spring. Show all posts

December 7, 2008

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.

July 27, 2008

at Sunday, July 27, 2008 Labels: , Posted by Billy 0 comments

While I was working on a Spring application, I saw the following error after deploying:

org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 1 in XML document from ServletContext resource [/WEB-INF/BCC-servlet.xml] is invalid; nested exception is org.xml.sax.SAXParseException: White spaces are required between publicId and systemId.



Here are the first few lines of the xml file the stack trace was referring to:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-2.0.xsd
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">


The report stateed the error was in Line 1, which was obviously not the case. The problem was the order of the schemaLocation values was incorrect. Here is the correct order:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">