John Doe
John Doe

Reputation: 191

GRAILS + Spring Security Plugin --- password is not encrypted when adding users

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

Answers (3)

IgniteCoders
IgniteCoders

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

John Doe
John Doe

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

V H
V H

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

Related Questions