开发者

Grails spring security / Acegi. Custom User + Password expired management

开发者 https://www.devze.com 2023-01-18 23:46 出处:网络
I\'m working on a grails legacy project. A domain class called User exists. It contains password, username, roles, etc.

I'm working on a grails legacy project. A domain class called User exists. It contains password, username, roles, etc.

This project uses Spring Security for role management. I would like to add expiration of credentials ( force the User to renew its password).

I've modified the User class. Not it implements the UserDetails interface.

However, when I start the server, I get this error>

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'messageSource': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException:

Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException:

Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is org.hibernate.PropertyNotFoundException:

Could not find a setter for property accountNonExpired in class com.company.app.user.User

Do I have to register some bean? I find the error quite confusing, since the interface doesn't asks for a setter method.

update

After investigating some more, I ran into my SecurityConfig.groovy, that looks A LOT like this (AcegiSecurity Plugin):

security {
   // see DefaultSecurityConfig.groovy for all settable/overridable properties

   active = true

   loginUserDomainClass = "User"
   authorityDomainClass = "Role"

 ....
}

My User class also looks A LOT like this:

/**
 * User domain class.
 */
class User {
   static transients = ['pass','passwordExpired','credentialsNonExpired']
   static hasMany = [authorities: Role]
   static belongsTo = Role
   /** Username */
   String username
   /** User Real Name*/
   String userRealName
   /** MD5 Password */
   String passwd
   /** enabled */
   boolean enabled

   String email
   boolean emailShow

   /** description */
   String description = ''

   /** plain password to create a MD5 password */
   String pass = '[secret]'

   static constraints = {
      username(blank: false, unique: true)
      userRealName(blank: false)
      passwd(blank: false)
      enabled()
   }

   public boolean isCredentialsNonExpired() {
         return true;
   }
}

I added a method to check if the password should expire or not for this class (isCredentialsNonExpired). I need this method to execute at login. Right now, its not.

So it looks like it's the Acegi approach I should take. Any thoughts开发者_运维问答? Its my understanding that Acegi uses Spring Security, right?


Are you using the Acegi plugin, or configuring it directly? If you use the Spring Security Core plugin this will be a lot easier since it's supported out of the box.

You probably don't want your User class to be your UserDetailsService class since it often has other baggage like mapped collections, etc. It can certainly work, but creating a simple data class is a better approach. It's convenient to subclass org.springframework.security.userdetails.User or org.springframework.security.core.userdetails.User depending on the version of Spring Security.

It looks like you just added a getter for accountNonExpired but if it's going to be persisted then it needs a setter too. If you're deriving the value and don't want that field to be in the database then you can add it to the transients list:

static transients = ['accountNonExpired']
0

精彩评论

暂无评论...
验证码 换一张
取 消