3
votes

I am just starting to learn Grails and Spring, and I have followed the official tutorial to create a login system. But I cannot login, "username or password does not match". I know that in 90% of the time this is due to double encoding or multiple data sources (which also leads to double encoding), but I am not doing either.

class BootStrap {

    def init = { servletContext ->

        def adminRole = new SecurityRole(authority: 'ROLE_ADMIN').save(failOnError: true, flush: true)
        def userRole = new SecurityRole(authority: 'ROLE_USER').save(failOnError: true, flush: true)

        def testUser = new User(username: 'admin', password: 'admin')
        testUser.save(failOnError: true, flush: true)

        SecurityUserSecurityRole.create testUser, adminRole, true

        assert User.count() == 1
        assert SecurityRole.count() == 2
        assert SecurityUserSecurityRole.count() == 1

        println testUser.username
        println testUser.password
    } 

spring-security-core:2.0-RC2
grails 2.3.3

1
@BenoitWickramarachi, yes, that's why I provided Bootstrap.groovy to show that I didn't do any explicit encoding. - maryokhin
Ok, is your datasource configured as dbCreate = "create-drop"? (because otherwise you are duplicating roles and users each time you launch the app). Or change your code to : def adminRole = SecRole.findByAuthority('ROLE_ADMIN') ?: new SecRole(authority: 'ROLE_ADMIN').save(failOnError: true) etc.. to avoid duplicating entries. - Benoit Wickramarachi
@BenoitWickramarachi, yes, I changed to what you offered and checked DB through MySQL Workbench, there are no duplicates - maryokhin
Not the solution to this question I dont think, but my issue was as others have said, double encoding. I was encoding the password in Bootstrap.groovy and also in the User controller - thanks! - andy mccullough

1 Answers

1
votes

I've had similar problems in a few projects and it has always been a double encoding issue for me. I am on an earlier version of the Spring Security Plugin but this technique works to ensure it does not double encode. Again, I'm on different versions but might be worth a try.

class User {
    // regular generated code should still be included
    boolean beforeInsertRunOnce = false
    boolean beforeUpdateRunOnce = false

    def beforeInsert() {
        if (! beforeInsertRunOnce) {
            beforeInsertRunOnce = true
            encodePassword()
        }
    }

    def afterInsert() {
        beforeInsertRunOnce = false
    }

    def beforeUpdate() {
        if (isDirty('password') && ! beforeUpdateRunOnce ) {
            beforeUpdateRunOnce = true
            encodePassword()
        }
    } 

    def afterUpdate() {
        beforeUpdateRunOnce = false
    }

    protected void encodePassword() {
        password = springSecurityService.encodePassword(password)
    }
}