我正在尝试在通过spring security core plugin创建的User
域实体上的Grais中实现密码验证。我在我的实体中添加了以下代码:
class User {
// Added by the spring security core plugin
String password
// Added by me
String passwordConfirm
static constraints = {
passwordConfirm blank:false, validator: { val, obj ->
if (!obj.password.equals(obj.passwordConfirm)) {
return "user.password.confirmation.error"
}
}
}
// other methods...
}
当password
与passwordConfirm
不匹配时,验证程序按预期工作。但是,当验证器成功通过并且实例即将持久化时,我会得到以下异常:
org.hibernate.AssertionFailure: null id in com.test.User entry (don't flush the Session after an exception occurs)
at com.shopify.RegistrationController$_closure2.doCall(RegistrationController.groovy:14)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)
我使用user.save(flush: true)
来保持我的实体。
当我删除验证时,我的实例成功地保存在数据库中,因此我假设我的验证器一定有问题。你对可能出错的地方有什么建议吗?我使用的是Grails版本2.0.4。
编辑:我保存我的实体的部分如下:
def register = {
def user = new User(params)
if (!user.save(flush:true, failOnError:true)) {
render view: 'register', model: [userInstance: user]
} else {
render view: 'success'
}
}
编辑:好的,我设法通过注释弹出安全核心插入的以下代码来完成这项工作:
def beforeInsert() {
// encodePassword()
}
def beforeUpdate() {
// if (isDirty('password')) {
// encodePassword()
// }
}
目前,我不知道为什么会这样,但我会检查出来。同时,如果有人对此有任何信息,我真的有兴趣与我分享。
编辑:发现此相关错误报告:http://jira.grails.org/browse/GRAILS-9083
答案 0 :(得分:0)
验证失败,因为在插入用户之前,它会散列您的密码,因此密码不再等于passwordConfirm,从而触发验证错误。
这是你在做什么:
保存前的:(
)def password = 1234
def passwordConfirm = 1234
password == passwordConfirm validation passes
在.save()期间。在插入被触发之前:
def password gets hashed:
def password = 1JO@J$O!@J$P!O@$JP!@O$J!@O$J!@
def passwordConfirm = 1234
password != passwordConfirm validation fails
从您的域中删除encodePassword()后:
def password = 1234
def passwordConfirm = 1234
password == passwordConfirm validation passes but now you have your password in plain texts inside your DB, you should never do this for security reasons.
简单修复将在单独的命令对象中进行验证,而不是在自己的域对象中进行验证,passwordConfirm甚至不应该在您的域类中。
实施例: 查看Spring Security UI的source,了解它如何使用命令对象处理控制器中的验证。