在Grails 2.0.3上,我按照教程安装了Spring Security Core并创建了User,UserRole和Role对象:http://blog.springsource.org/2010/08/11/simplified-spring-security-with-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 )
}
有什么想法吗?
答案 0 :(得分:6)
Gaaaahh。找到了这个: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标志创建了一个解决方法,以防止用户中的多个编码:
class User {
boolean isPasswordEncoded = false
....snip....
def beforeInsert() {
if ( !isPasswordEncoded )
{
isPasswordEncoded = true
encodePassword ()
}
}
def beforeUpdate() {
if (isDirty('password')) {
isPasswordEncoded = false
encodePassword()
}
}
....snip....
}
答案 1 :(得分: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
}
答案 2 :(得分:0)
我确实有类似的问题。是因为我忘了添加
grails.plugin.springsecurity.userLookup.userDomainClassName ='yourpackage.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName =yourpackage.UserRole'
grails.plugin.springsecurity.authority.className ='yourpackage.Role'
之后认证工作正常。