Rails 4-仅当当前密码正确时才允许更改密码 [英] Rails 4 - Allow password change only if current password is correct

查看:131
本文介绍了Rails 4-仅当当前密码正确时才允许更改密码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用中,用户可以编辑其个人资料信息.在编辑配置文件表单上,用户可以更改所有字段(名称,标题等).在同一表单上有三个字段:current_passwordpasswordpassword_confirmation.我正在使用bcrypthas_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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆