针对 Rails 中的空白密码进行验证
Validating against blank password in Rails
我为我的 User
模型添加了密码密码验证:
validates :password, presence: true
validates :password, confirmation: { case_sensitive: true }
但是当我想更新 users
上的其他字段时,这些验证使交易无效,因为 password
不存在。
通过一些研究,我意识到如果 password
不存在,我可以跳过这些验证:
validates :password, presence: true, if: :validate_password?
validates :password, confirmation: { case_sensitive: true }, if: :validate_password?
def validate_password?
password.present? || password_confirmation.present?
end
但是,现在当我提交空白密码和密码确认时,validate_password?
returns false
。我真的不明白发生了什么,因为
@user.update_attributes(password_reset_edit_params)
returns true
其中
password_reset_edit_params
是 <ActionController::Parameters {"password"=>"", "password_confirmation"=>""} permitted: true>
但里面
def validate_password?
password.present? || password_confirmation.present?
end
password
和 password_confirmation
评估为 nil
,我的 @user
密码没有更新为空字符串。
我应该提到我正在使用 Bcrypt,@user.password
实际上总是会评估为 nil
,而 password_digest
可用。
那么解决方法是什么?最后我想我的问题很简单:
如何在我不尝试提交密码时忽略密码验证,但在提交空字符串时允许这些验证?
我突然想到我可以在控制器中添加一个不允许传递空字符串的条件,但是必须有一个巧妙的方法来解决这个问题。
非常感谢任何帮助。谢谢!
在 Rails 中,您不是在验证参数,而是在验证模型。
不要"skip validation if the password is not present"。这就是验证的目的。验证旨在验证 模型 ,而不是参数。如果模型的密码为空,并且需要密码,则该模型无效。总是。
but then when I wanted to update other fields on users, those validations were rendering the transaction invalid, as password was not present.
这不是因为密码不存在,而是因为用户实例中没有密码。它的工作方式应该是:
- 使用密码创建用户并验证:
User.create(name: "Me", password: "something that isn't nil")
- 用户已更新:
User.update(name: "New name") # password is inside the model still so it is still valid
这就是它的工作原理。如果您希望用户能够拥有零/空密码,那么您不应该尝试在模型中放置存在验证。
如果你使用 Bcrypt 和 digest,你可以在你的模型中使用,例如
has_secure_password
validates :password, length: { minimum: 8 }, allow_blank: true
在这种情况下,验证仅适用于设置和更改密码。
如果不修改密码就不需要输入密码。
另一种方式
validates :password, presence: true, on: :create
最终我只是在用户模型上验证密码格式和确认:
validates :password, confirmation: true,
length: {within: 6..40},
allow_blank: true
并根据控制器中的空白密码/password_confirmation 清理输入数据。
if password_reset_edit_params[:password].blank? || password_reset_edit_params[:password_confirmation].blank?
@user.errors[:password] << "can't be blank" if password_reset_edit_params[:password].blank?
@user.errors[:password_confirmation] << "can't be blank" if password_reset_edit_params[:password_confirmation].blank?
render 'edit'
我为我的 User
模型添加了密码密码验证:
validates :password, presence: true
validates :password, confirmation: { case_sensitive: true }
但是当我想更新 users
上的其他字段时,这些验证使交易无效,因为 password
不存在。
通过一些研究,我意识到如果 password
不存在,我可以跳过这些验证:
validates :password, presence: true, if: :validate_password?
validates :password, confirmation: { case_sensitive: true }, if: :validate_password?
def validate_password?
password.present? || password_confirmation.present?
end
但是,现在当我提交空白密码和密码确认时,validate_password?
returns false
。我真的不明白发生了什么,因为
@user.update_attributes(password_reset_edit_params)
returns true
其中
password_reset_edit_params
是 <ActionController::Parameters {"password"=>"", "password_confirmation"=>""} permitted: true>
但里面
def validate_password?
password.present? || password_confirmation.present?
end
password
和 password_confirmation
评估为 nil
,我的 @user
密码没有更新为空字符串。
我应该提到我正在使用 Bcrypt,@user.password
实际上总是会评估为 nil
,而 password_digest
可用。
那么解决方法是什么?最后我想我的问题很简单:
如何在我不尝试提交密码时忽略密码验证,但在提交空字符串时允许这些验证?
我突然想到我可以在控制器中添加一个不允许传递空字符串的条件,但是必须有一个巧妙的方法来解决这个问题。
非常感谢任何帮助。谢谢!
在 Rails 中,您不是在验证参数,而是在验证模型。
不要"skip validation if the password is not present"。这就是验证的目的。验证旨在验证 模型 ,而不是参数。如果模型的密码为空,并且需要密码,则该模型无效。总是。
but then when I wanted to update other fields on users, those validations were rendering the transaction invalid, as password was not present.
这不是因为密码不存在,而是因为用户实例中没有密码。它的工作方式应该是:
- 使用密码创建用户并验证:
User.create(name: "Me", password: "something that isn't nil")
- 用户已更新:
User.update(name: "New name") # password is inside the model still so it is still valid
这就是它的工作原理。如果您希望用户能够拥有零/空密码,那么您不应该尝试在模型中放置存在验证。
如果你使用 Bcrypt 和 digest,你可以在你的模型中使用,例如
has_secure_password
validates :password, length: { minimum: 8 }, allow_blank: true
在这种情况下,验证仅适用于设置和更改密码。
如果不修改密码就不需要输入密码。
另一种方式
validates :password, presence: true, on: :create
最终我只是在用户模型上验证密码格式和确认:
validates :password, confirmation: true,
length: {within: 6..40},
allow_blank: true
并根据控制器中的空白密码/password_confirmation 清理输入数据。
if password_reset_edit_params[:password].blank? || password_reset_edit_params[:password_confirmation].blank?
@user.errors[:password] << "can't be blank" if password_reset_edit_params[:password].blank?
@user.errors[:password_confirmation] << "can't be blank" if password_reset_edit_params[:password_confirmation].blank?
render 'edit'