Ruby on rails 为什么添加密码恢复后密码验证不起作用?

Ruby on rails 为什么添加密码恢复后密码验证不起作用?,ruby-on-rails,ruby,authentication,password-encryption,actioncontroller,Ruby On Rails,Ruby,Authentication,Password Encryption,Actioncontroller,面对一个我不清楚的问题。 我在注册时使用了密码验证 def pass\u val 如果密码摘要计数(“a-z”)错误出现在发送密码重置方法中。 向这个方法添加了(:validate=>false),它成功了 def发送\密码\重置 确认令牌 self.password\u reset\u sent\u at=Time.zone.now 拯救(:validate=>false) AuthorMailer.password\u重置(self.deliver)! 结束 在vallidation中,我

面对一个我不清楚的问题。 我在注册时使用了密码验证

def pass\u val

如果密码摘要计数(“a-z”)错误出现在
发送密码重置方法中。
向这个方法添加了
(:validate=>false)
,它成功了

def发送\密码\重置
确认令牌
self.password\u reset\u sent\u at=Time.zone.now
拯救(:validate=>false)
AuthorMailer.password\u重置(self.deliver)!
结束

在vallidation中,我使用
密码

似乎您自己已经找到了解决方案。但是,我不确定您是否理解发生这种情况的原因

让我们从一个重要的事实开始:
password\u digest
不包含密码,而是密码的哈希版本。(哈希函数的结果也称为摘要。)您需要将验证添加到
password
属性,因为该属性包含实际密码

将新密码分配给作者时,密码和密码摘要都将被分配一个新值。您可以想象
密码设置器的外观如下:

def password=(password)
  @password = password
  @password_digest = do_some_hash_magic(password)
end
因为
密码
是在您将其分配给作者时设置的,所以您可以验证其内容

要知道的另一件重要事情是,实际密码永远不会保存到数据库中,只有密码摘要(出于安全原因)会保存到数据库中。因此,当您(重新)从数据库加载实例时,
密码
设置为
,因为应用程序不再知道它是什么

与使用
save(validate:false)
跳过验证不同,我建议使用该选项或使仅当
密码
不是
nil
时才触发验证

validates :password, length: { in: 8..255 }, allow_nil: true

validates :password, format: { with: /\p{Lower}/,    message: :no_lower   }, allow_nil: true
validates :password, format: { with: /\p{Upper}/,    message: :no_upper   }, allow_nil: true
validates :password, format: { with: /\p{Digit}/,    message: :no_digit   }, allow_nil: true
validates :password, format: { with: /[\p{S}\p{P}]/, message: :no_special }, allow_nil: true
或者,您可以更显式地使用带有自定义上下文的选项,仅在希望验证满足以下条件时触发验证:

validates :password, length: { in: 8..255 }, on: :password

validates :password, format: { with: /\p{Lower}/,    message: :no_lower   }, on: :password
validates :password, format: { with: /\p{Upper}/,    message: :no_upper   }, on: :password
validates :password, format: { with: /\p{Digit}/,    message: :no_digit   }, on: :password
validates :password, format: { with: /[\p{S}\p{P}]/, message: :no_special }, on: :password
上下文不必以属性命名,使用
:foo
而不是
:password
也可以。然后,您可以在调用
valid?
save
时通过传递上下文来运行这些验证

author.valid?(:password)
author.save(context: :password)
如果您使用Rails 5或更高版本,如果您希望混合运行验证,那么可以将多个上下文作为一个数组传递<代码>作者.有效?([:创建,:密码])


有关所用正则表达式的更多信息,请查看。

密码摘要
不是密码,因此您不应该对其进行任何内容检查。
发送密码重置
做什么?显示代码。我猜它发送一封带有链接的电子邮件,当用户点击链接时会发生什么?显示代码,我猜它显示了一个表单,当用户提交表单时会发生什么?显示代码
author.valid?(:password)
author.save(context: :password)