BCrypt在ruby中检查密码对数据库的问题

时间:2014-05-16 16:43:32

标签: ruby-on-rails ruby bcrypt

我对ruby和rails相对较新,如果我的任何代码有点乱或者不遵循一般约定,那就很抱歉。欢迎提出任何意见。

我尝试使用BCrypt创建用户/密码身份验证系统但是当我去检查密码时,它总是会失败。

User.rb

#encryption of password
before_save :encrypt_password
after_save :clear_password

def encrypt_password
  if password.present?
    self.password_hash = Password.create(password)
  end
end

def clear_password
  self.password = nil
end

#authentication
def self.authenticate(username_or_email="", login_password="")
  if EMAIL_REGEX.match(username_or_email)
    user = User.find_by_email(username_or_email)
  else
    user = User.find_by_username(username_or_email)
  end
  if user && user.password_hash == login_password
    return user
  else
    return false
  end
end

users_controller.rb

def new
  @user = User.new
end

def create
  @user = User.new( user_params )
  if @user.save 
    flash[:notice] = "You've signed up successfully"
    flash[:color] = "valid"
  else
    flash[:notice] = "Form is invalid"
    flash[:color] = "invalid"
  end
  render "new"
end

sessions_controller.rb

  def login_attempt
    authorized_user = User.authenticate(params[:username_or_email], params[:login_password])
    if authorized_user
      session[:user_id] = authorized_user.id
      @current_user = authorized_user
      logger.debug "User has been authorized"
      flash[:notice] = "Welcome again, you logged in as #{authorized_user.username}"
      redirect_to(:action => 'home')
    else
      flash[:notice] = "Invalid Username or Password"
      flash[:color] = "invalid"
      render "login"
    end
  end

任何帮助都将不胜感激,谢谢。

2 个答案:

答案 0 :(得分:0)

我打赌问题是将存储密码的哈希与普通密码字符串进行比较:

def login_attempt
    authorized_user = User.authenticate(params[:username_or_email], params[:login_password])

def self.authenticate(username_or_email="", login_password="")
  ...
  if user && user.password_hash == login_password
  #          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

您可能需要修复与user.password_hash == Password.new(login_password) 的比较。 您只需确保login_password不包含某些尾随字符(如换行符)或self.password_hash在此期间不会被更改。

还注意到clear_password方法中的可能拼写错误 - self.password = nil而不是self.password_hash = nil

作为旁注,我会将身份验证留给某些成熟模块,例如Devise(警告:需要启用javascript)

答案 1 :(得分:0)

所以我找到了一种不同的方法来使用BCrypt。 Rails有一个内置的has_secure_password,如果users表中的列被称为password_digest,它就可以工作。它的工作原理如下:

<强> sessions_controller.rb

  def login_attempt
    if EMAIL_REGEX.match(params[:username_or_email])
      user = User.find_by_email(params[:username_or_email])
    else
      user = User.find_by_username(params[:username_or_email])
    end

    authorized_user = user.authenticate(params[:login_password])

    if authorized_user
      session[:user_id] = authorized_user.id
      @current_user = authorized_user
      redirect_to(:action => 'home')
    else
      flash[:notice] = "Invalid Username or Password"
      flash[:color] = "invalid"
      render "login"
    end
  end

并且在 user.rb 类文件中必须有一行代码:

has_secure_password