2012-05-22 6 views
3

На Grails 2.0.3, я установил Spring Security Сердечник и создал пользователь, UserRole и роль объектов в соответствии с учебником: http://blog.springsource.org/2010/08/11/simplified-spring-security-with-grails/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) 
} 

Любые идеи?

ответ

6

Gaaaahh. Нашел это: http://jira.grails.org/browse/GRAILS-8237 - по-видимому, beforeInsert вызывается в каждом домене для каждого источника данных. Это означает, что в моем объекте пользователя 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.... 
} 
3

код решение опубликовано оригинальный ответ не работает для обновления. А также не рассматривает несколько обновлений для одного экземпляра объекта. Я использую отдельные флаги для операций вставки и обновления, отмечаю их как переходные, чтобы они не сохранялись, и используйте обработчик события 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 
    } 
0

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

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

После этого была выполнена аутентификация.