Tutorial :Acegi/Spring Security Grails plug-in not seeing changes to a User instance



Question:

I am writing a web app in Grails with the Acegi/Spring Security plug-in, and am having trouble getting it to see changes I make to User instances. I have only been working with Groovy/Grails for about three weeks, so please forgive me if this problem is trivial, since I have been poring over mailing lists and tutorials trying to find the answer.

I have been adding new attributes to the User domain class whenever I need a User to contain more information such as an email confirmation token or real name, since I couldn't find any recommendations to the contrary. Everything seems to be fine for creating new users, but when I edit the user, the changes show up in the user list, but the Acegi tag libraries and associated functions don't seem to see the changes.

Here is the relevant snippet from UserController.update():

def person = User.get(params.id)  //...snip error checking...    //Update user attributes  person.username = params.email  person.email = params.email  person.userRealName = params.userRealName    //Attempt to save changes  if (person.save()) {      //If successful, redirect back to profile viewing page      redirect action: show, id: person.id      return  }  else {      //Otherwise, show errors and edit again      render view: 'edit', model: buildPersonModel(person)      return  }  

After this code runs, I can see the changes if I always get user data by ID, but not if I use the Acegi tags or functions. For example, this does not work:

loggedInUserInfo(field:'realName')  

But this does:

User.get(loggedInUserInfo(field:'id').toLong()).realName  

The new information sometimes shows up after I log out and in again, but usually it doesn't, often not showing up even after three or more relogs. Also, I tried adding "flush:true" to person.save() with no effect.

(Peripheral question: is it bad for me to be fiddling with the User class like this? If not, what's the best way to add information to it?)

Update after more investigation: It looks like if I use loggedInUserInfo() in a normal page, it works fine, but if I use it inside a layout, it exhibits the behavior I described. Could there be some odd caching thing going on?


Solution:1

I have a workaround for this issue and i've also created a JIRA entry for the problem.

There seems to be a bug in how Acegi updates it's users internally. I provide a workaround in the form of a grails filter which updates the user's authorities manually every time a controller is accessed. Not ideal but it works.

Cheers,


Solution:2

Did you run grails generate-manager after modifying your user class?


Solution:3

Acegi caches User info, if I remember correctly. Check the 'DefaultSecurityConfig' file (I think that's the name, under config/) for disabling user info cache. You can also call some method on authenticateService (can't remember what method right now) to evict the user cache.

You may be able to find the latter within the UserController#update closure.


Solution:4

I faced same problem, and followed advice given by Maximilian Schweitzer above. It did not work for me in the beginning.

Give these steps a try and see if it resolves the issue:

  1. I ran generate-manager as per answer above by Maximilian Schweitzer .
  2. Tried to login with users created before I ran generate-manager - Didn't work
  3. I created new user (with new UserController, gsp, etc)
  4. Tried to login with new user works just fine.
  5. Deleted old users created before and recreated them. It worked fine.

Though not sure if it applies to your situation.

HTH!


Solution:5

I was facing the same problem. My solution was to make an update of the acegi plugin to version 0.5.1 (acegi 0.5.1 -- Grails Spring Security 2.0 Plugin).

Then I've set at /plugins/acegi-0.5.1/grails-app/conf/DefaultSecurityConfig.groovy

cacheUsers = false  

and now voila! it is working!

Luis


Solution:6

You have to reset the authenticated user. The code below does just that (from this blog).

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    ...    def refreshAuthenticatedUser(user) {      GrantedAuthority[] auths = user.authorities.collect {          new GrantedAuthorityImpl(it.authority)      }      def grailsUser = new GrailsUserImpl(              user.username,              "",              user.enabled,              true,              true,              true,              auths,              user)      def authToken = new UsernamePasswordAuthenticationToken(grailsUser, '', auths)      SecurityContextHolder.context.authentication = authToken    }  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »