Reputation: 191
Clean installation of Grails 3.2.9 + Spring Security Plugin 3.1.0.
Default User/Role/UserRole domains created by s2-quickstart com.raf.app User Role
.
BootStrap init code:
...
def init = { servletContext ->
def adminRole = Role.findOrSaveWhere(authority: 'ROLE_ADMIN')
def user = User.findOrSaveWhere(username: 'raf',
password: 'password')
if (!user.authorities.contains(adminRole)){
UserRole.create(user, adminRole)
}
...
I saw in a tutorial that the password for this user should appear encoded in the db (using dbconsole to check this out), but in my case it does not (it's just 'password' like in here).
So I went to the User domain and made these horrible changes:
def beforeUpdate() {
encodePassword()
}
protected void encodePassword() {
password = springSecurityService?.passwordEncoder ? springSecurityService.encodePassword(password) : springSecurityService.encodePassword(password)
}
And this on the other hand throws NullPointer exception. Why?
Cannot invoke method encodePassword() on null object
So what do I do to have my passwords encrypted, like I like 'em?
Upvotes: 1
Views: 1876
Reputation: 4980
If you setup Spring Security manually insted of using the command provided. Maybe you forgot to add the UserPasswordEncoderListener
class and define it in resources.groovy
as a bean. This class should encode the password automaticly
UserPasswordEncoderListener:
import grails.plugin.springsecurity.SpringSecurityService
import groovy.transform.CompileStatic
import org.grails.datastore.mapping.core.Datastore
import org.grails.datastore.mapping.engine.event.*
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.ApplicationEvent
@CompileStatic
class UserPasswordEncoderListener extends AbstractPersistenceEventListener {
@Autowired
SpringSecurityService springSecurityService
UserPasswordEncoderListener(final Datastore datastore) {
super(datastore)
}
@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.isDirty('password')))) {
event.getEntityAccess().setProperty("password", encodePassword(u.password))
}
}
}
@Override
boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
eventType == PreUpdateEvent || eventType == PreInsertEvent
}
private String encodePassword(String password) {
springSecurityService?.passwordEncoder ? springSecurityService.encodePassword(password) : password
}
}
resources.groovy
beans = {
userPasswordEncoderListener(UserPasswordEncoderListener, ref('hibernateDatastore'))
}
UserPasswordEncoderListener
should be placed under src/main/groovy/com.mypackage...
Upvotes: 1
Reputation: 191
Okay, so I believe the NullPointer was caused by what vahid described.
However, to have my passwords encoded by default, I had to set
autowire: true
in Configs/application.yml. Don't ask me why, but it works.
Upvotes: 1
Reputation: 8587
So to explain what is going on in the hope it makes more sense
You have simply told the code to repeat the encrypt function if it cant find encode.
Above code by default is here
password = springSecurityService?.passwordEncoder ? springSecurityService.encodePassword(password) : password
This says :
if (springSecurityService?.passwordEncoder) {
springSecurityService.encodePassword(password)
} else {
password
}
So you see you have told it to do what it can't
I am on grails 3.2.8 and using:
compile 'org.grails.plugins:spring-security-core:3.1.2'
Upvotes: 1