I'm using Grails 3.3.2 with the mongoDB plugin (v6.1.4) and Spring Security Core plugin (v3.2.0).
I have the following UserPasswordEncoderListener
with the following persistenceEvent method:
@Override
protected void onPersistenceEvent(AbstractPersistenceEvent event) {
if (event.entityObject instanceof User) {
User u = (event.entityObject as User)
if (u.password && (event.eventType == EventType.PreInsert || (event.eventType == EventType.PreUpdate && u.hasChanged('password')))) {
event.getEntityAccess().setProperty("password", encodePassword(u.password))
}
}
}
The problem is the hasChanged
call always return true every time I save a user object that has NO updates causing an already encoded password to be re-encoded and thereby breaking authentication.
One workaround will be to do it the old way and just retrieve the original password from the db and compare them before encoding but I'm wondering why hasChanged
is falsely returning true.
I tested that hasChanged
behaves correctly elsewhere by running the following in the groovy console:
def user = User.findByEmail("[email protected]")
println "Result: "+ user.hasChanged('password')
The result is Result: false
.
Why does it NOT work in the persistence listener class?
FYI: I have the following bean defined in resources.groovy:
userPasswordEncoderListener(UserPasswordEncoderListener,ref('mongoDatastore'))
Have you tried using
isDirty()
rather thanhasChanged()
in your listener?For example:
More info is available at: https://grails-plugins.github.io/grails-spring-security-core/3.2.x/index.html#tutorials