我有一个包含3个字段的组域对象 - 用户名,密码和电子邮件地址 在保存对象之前,我对电子邮件地址进行了模糊处理,因此它不作为业务需求存储在我们数据库的纯文本中
当我在域对象上调用validate时,我注意到了一些奇怪的行为。 字段的约束如下
userName (nullable: false, unique: false,blank: false, size: 4..200,widget: "textField", matches: "[a-zA-Z0-9, .-@#~{}!£%&*^()-_]+")
password (nullable: false, unique: false,blank: false, size: 4..200,widget: "textField", password: true, matches: "[a-zA-Z0-9, .-@#~{}!£%&*^()-_]+")
emailAddress (nullable: false, unique: false,blank: false, size: 5..200,widget: "textField",email: true, matches: "[a-zA-Z0-9, .-@#~{}!£%&*^()-_]+")
对于该对象,我验证它以确保所有值都符合预期(emailAddress尚未进行模糊处理) 如果有效,我会混淆电子邮件地址,然后使用validate:false
的值调用save奇怪的行为如下 如果我填写有效的电子邮件地址和有效密码 - 该对象在userName字段上验证失败,因为它不能为空
如果我填写了有效的电子邮件地址和有效的用户名 - 该对象在密码字段上验证失败,因为它不能为空并且也在电子邮件地址上,并且它显示消息中电子邮件地址的模糊值
我首先想到的是混淆导致问题,但是在输入密码字段的情况下它可以正常工作 它与两种情况完全相同的代码流。
在我混淆电子邮件地址后,grails是否可能为未填写密码字段的方案调用validate方法?
代码流程如下
def userLoginUserInstance = UserLoginUser.get(params.id)
userLoginUserInstance.properties = params
if (userLoginUserInstance.validate()) {
//perform updates to database by obfuscating email address first - working fine
} else {
def newObfuscatedEmailAddress = userLoginUserInstance.emailAddress.encodeAsBase64();
userLoginUserInstance.setEmailAddress(newObfuscatedEmailAddress);
render(view: "edit", model: [userLoginUserInstance: userLoginUserInstance])
}
验证失败时电子邮件地址被混淆的原因是gsp读取的瞬态变量具有getter而不是deObfuscates电子邮件地址。当上面的代码运行时没有设置用户名,它工作正常,电子邮件地址显示为正常。 如果密码为空,则显示密码错误,但混淆的电子邮件地址也显示为无效。
On进一步分析,当我运行以下代码行时,验证问题正在发生
userLoginUserInstance.setEmailAddress(newObfuscatedEmailAddress);
我理解为什么会发生这种情况,因为从数据库中检索了userLoginUserInstance。 令我困惑的是,这并非在所有场景中都发生
答案 0 :(得分:1)
验证错误正在发生,因为您试图将Base64
字符串存储到具有电子邮件约束的属性中:
"foo@bar.com".encodeAsBase64()
结果
Zm9vQGJhci5jb20=
所以现在当你的User
实体再次刷新到数据库时,当然会发生另一次验证,抱怨这不是有效的电子邮件地址。
为什么在所有情况下都没有提出验证错误的原因可能是您没有强制执行user.save()
或user.save(flush:true)
。
这意味着电子邮件地址不会更新广告,但过了一段时间。为了更好地了解发生了什么,在分配电子邮件后添加另一个验证块。
答案 1 :(得分:0)
很抱歉没有尽快回复
我通过将新对象传递回视图而不是数据库中的对象来解决此问题 因为我要求对电子邮件地址进行模糊处理,所以这个用例真的过于复杂了
感谢您对这一个人的帮助
此致 达明