Following on from my post on how to log in a user using the Grails Acegi/Spring Security plugin I stumbled into a new use for the same code when I tried to update a user’s own details while logged in. The security plugin caches the user’s domain object so any changes are not seen until the next login (wholly unhelpful when you’re trying to implement account management on a Website!).
Stop Caching the User Domain Object
There are a couple of ways to solve this problem, the brute-force approach is to turn off caching of the domain object so it’s reloaded on each call. Turning off user caching is simple in the latest version of the Spring Security plugin, just add this line to your SecurityConfig.groovy file:
cacheUsers = false
Refresh the Authentication Token
Of course there is a performance hit associated with turning off caching, so instead it’s much more useful to be able to refresh the domain object only when needed. This can be achieved using the same method as logging in a user when the password is not available, as described in my previous post:
import org.springframework.security.context.SecurityContextHolder import org.springframework.security.providers.UsernamePasswordAuthenticationToken import org.codehaus.groovy.grails.plugins.springsecurity.GrailsUserImpl import org.springframework.security.GrantedAuthority import org.springframework.security.GrantedAuthorityImpl ... private def refreshUserPrincipal(username) { def user = User.findByUsername(username) GrantedAuthority[] auths = user.authorities.collect { new GrantedAuthorityImpl(it.authority) } def grailsUser = new GrailsUserImpl( user.username, "", true, true, true, true, auths, user) def authToken = new UsernamePasswordAuthenticationToken( grailsUser, '', auths) SecurityContextHolder.context.authentication = authToken }
So by calling the refreshUserPrincipal method after making updates to the user’s domain object you can maintain the benefits of caching while continuing to use the authenticateService.userDomain object to read up-to-date properties of the user.
Update
Also see my post on AOP where I show how this update method can be extended using aspect oriented programming.
Great tutorial that was a big help to me.
Thanks and keep up the good work.
Regards from Zurich, Switzerland
Peter
what about the springSecurityService.reauthenticate() method?
Doesn’t it work in the same way?