Grails 2 не может войти в систему с безопасностью Spring при использовании нескольких баз данных

В Grails 2.0.3 я установил Spring Security Core и создал объекты User, UserRole и Role в соответствии с руководством: http://blog.springsource.org/2010/08/11/simplified-spring-безопасность-с-grails/

Все шло хорошо, пока я не решил добавить второй источник данных для подготовки к доступу к объектам из другой базы данных. DataSource.groovy выглядит так:

test {
    dataSource_product {
        dbCreate = "update"
        url = "jdbc:mysql://localhost/products"
        pooled = true
        driverClassName = "com.mysql.jdbc.Driver"
        username = "blah"
        password = "blah"
        loggingSql = true
        dialect = 'org.hibernate.dialect.MySQL5InnoDBDialect'
    }
    dataSource {
        dbCreate = "update"
        url = "jdbc:mysql://localhost/core"
        pooled = true
        driverClassName = "com.mysql.jdbc.Driver"
        username = "blah"
        password = "blah"
        loggingSql = true
        dialect = 'org.hibernate.dialect.MySQL5InnoDBDialect'
    }
}

Теперь я не могу войти в систему, хотя все, что я сделал, это добавил datasource_product. Если я прокомментирую это и воссоздам пользователей (в Bootstrap.groovy), я смогу снова войти в систему. Bootstrap.groovy содержит:

def init =
{ servletContext ->

    // Add in roles
    Role.withTransaction { 
        def adminRole = Role.findByAuthority ( Role.ROLE_ADMIN ) ?: new Role ( authority: Role.ROLE_ADMIN ).save ( failOnError: true )

        def adminUser = User.findByUsername ( 'admin' ) ?: new User (
                username: 'blah',
                password: 'blah',
                enabled: true ).save ( failOnError: true )
        if ( !adminUser.authorities.contains ( adminRole ) ) UserRole.create ( adminUser, adminRole )
}

Любые идеи?


person user1409255    schedule 22.05.2012    source источник


Ответы (3)


Гааааа. Нашел это: http://jira.grails.org/browse/GRAILS-8237 - по-видимому, beforeInsert вызывается для каждого домена для каждого источника данных. Это означает, что в моем объекте User encodePassword вызывается дважды - я дважды кодирую пароль:

def beforeInsert() {
    encodePassword()
}

def beforeUpdate() {
    if (isDirty('password'))
        encodePassword()
}

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

Я видел патч в JIRA, но пока он не попал в релиз, я создал обходной путь, используя флаг isPasswordEncoded, чтобы предотвратить многократное кодирование в User:

class User {
    boolean isPasswordEncoded = false
....snip....
    def beforeInsert() {
        if ( !isPasswordEncoded )
        {
            isPasswordEncoded = true
            encodePassword ()
        }
    }

    def beforeUpdate() {
        if (isDirty('password')) {
            isPasswordEncoded = false
            encodePassword()
        }
    }
....snip....
}
person user1409255    schedule 22.05.2012

Решение для кода, опубликованное исходным ответом, не работает для обновления. А также не учитывает несколько обновлений одного и того же экземпляра объекта. Я использую отдельные флаги для операций вставки и обновления, помечаю их как временные, чтобы они не сохранялись, и использую обработчик событий afterUpdate() для сброса этих флагов.

    static transients = ['beforeInsertRunOnce','beforeUpdateRunOnce']
    boolean beforeInsertRunOnce
    boolean beforeUpdateRunOnce

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

    def afterInsert() {
        beforeInsertRunOnce = false
    }

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

    def afterUpdate() {
        beforeUpdateRunOnce = false
    }
person winstaan74    schedule 10.01.2013

У меня была аналогичная проблема. Потому что я забыл добавить

grails.plugin.springsecurity.userLookup.userDomainClassName ='yourpackage.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName =yourpackage.UserRole'
grails.plugin.springsecurity.authority.className ='yourpackage.Role'

После этого аутентификация заработала.

person Vadim    schedule 05.07.2014