Rails 4-仅当当前密码正确时才允许更改密码 [英] Rails 4 - Allow password change only if current password is correct
问题描述
在我的应用中,用户可以编辑其个人资料信息.在编辑配置文件表单上,用户可以更改所有字段(名称,标题等).在同一表单上有三个字段:current_password
,password
和password_confirmation
.我正在使用bcrypt
的has_secure_password
功能进行密码身份验证.我根本没有使用Devise.
In my app, users can edit their profile information. On the edit profile form, the user can make changes to all fields (name, title, and more). On this same form are three fields: current_password
, password
, and password_confirmation
. I am using bcrypt
's has_secure_password
feature for password authentication. I am NOT using Devise at all.
我希望用户仅在提供正确的当前密码后才能更改其密码.在使用我的Users控制器的update
方法中的以下代码之前,我已经使用了以下代码:
I want users to only be able to change their password if they have supplied a correct current password. I've got this working before with the following code in the update
method of my Users controller:
# Check if the user tried changing his/her password and CANNOT be authenticated with the entered current password
if !the_params[:password].blank? && !@user.authenticate(the_params[:current_password])
# Add an error that states the user's current password is incorrect
@user.errors.add(:base, "Current password is incorrect.")
else
# Try to update the user
if @user.update_attributes(the_params)
# Notify the user that his/her profile was updated
flash.now[:success] = "Your changes have been saved"
end
end
但是,这种方法的问题在于,如果仅当前密码不正确,它将放弃对用户模型的所有更改.我想将所有更改保存到用户模型,但是如果当前密码不正确,则不要保存密码更改.我已经尝试过像这样拆分IF语句:
However, the problem with this approach is that it discards all changes to the user model if just the current password is incorrect. I want to save all changes to the user model but NOT the password change if the current password is incorrect. I've tried splitting up the IF statements like so:
# Check if the user tried changing his/her password and CANNOT be authenticated with the entered current password
if !the_params[:password].blank? && !@user.authenticate(the_params[:current_password])
# Add an error that states the user's current password is incorrect
@user.errors.add(:base, "Current password is incorrect.")
end
# Try to update the user
if @user.update_attributes(the_params)
# Notify the user that his/her profile was updated
flash.now[:success] = "Your changes have been saved"
end
这不起作用,因为即使当前密码不正确,用户也可以更改其密码.单步执行代码时,尽管当前密码不正确".通过update_attributes
方法运行后,错误被添加到@user
,似乎忽略了此错误消息.
This doesn't work because the user is able to change his/her password even if the current password is incorrect. When stepping through the code, although the "Current password is incorrect." error is added to @user
, after running through the update_attributes
method, it seems to ignore this error message.
顺便说一句,current_password
字段是我的用户模型中的虚拟属性:
By the way, the current_password
field is a virtual attribute in my User model:
attr_accessor :current_password
两个小时以来,我一直在试图解决这个问题,所以我真的可以使用一些帮助.
I've been stuck trying to figure this out for a couple of hours now, so I can really use some help.
谢谢!
感谢 papirtiger ,我的工作正常了.我从他的回答中稍微修改了代码.下面是我的代码.请注意,这两个代码段都可以正常工作.
Thanks to papirtiger, I got this working. I changed the code around a little bit from his answer. Below is my code. Note that either code snippet will work just fine.
在用户模型(user.rb)
class User < ActiveRecord::Base
has_secure_password
attr_accessor :current_password
# Validate current password when the user is updated
validate :current_password_is_correct, on: :update
# Check if the inputted current password is correct when the user tries to update his/her password
def current_password_is_correct
# Check if the user tried changing his/her password
if !password.blank?
# Get a reference to the user since the "authenticate" method always returns false when calling on itself (for some reason)
user = User.find_by_id(id)
# Check if the user CANNOT be authenticated with the entered current password
if (user.authenticate(current_password) == false)
# Add an error stating that the current password is incorrect
errors.add(:current_password, "is incorrect.")
end
end
end
end
现在我的Users控制器中的代码很简单:
And the code in my Users controller is now simply:
# Try to update the user
if @user.update_attributes(the_params)
# Notify the user that his/her profile was updated
flash.now[:success] = "Your changes have been saved"
end
推荐答案
您可以在模型级别添加自定义验证,以检查密码是否已更改:
You could add a custom validation on the model level which checks if the password has changed:
class User < ActiveRecord::Base
has_secure_password
validate :current_password_is_correct,
if: :validate_password?, on: :update
def current_password_is_correct
# For some stupid reason authenticate always returns false when called on self
if User.find(id).authenticate(current_password) == false
errors.add(:current_password, "is incorrect.")
end
end
def validate_password?
!password.blank?
end
attr_accessor :current_password
end
这篇关于Rails 4-仅当当前密码正确时才允许更改密码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!