尝试登录时出现Ruby-“ BCrypt :: Errors :: InvalidHash”

我正在尝试完成一个项目。 我正在使用用户模型。当我注册时,一切似乎都很好。 但是,当我尝试登录同一成员时,会出现此错误。

我们很抱歉,但有些不对劲。heroku日志文件显示错误为:

BCrypt::Errors::InvalidHash (invalid hash):
  app/controllers/sessions_controller.rb:8:in `create'

我的* sessions_controller *是:

class SessionsController < ApplicationController

  def new
  end

   def create
    user = User.find_by_email(params[:session][:email])
    if user && user.authenticate(params[:session][:password])
      sign_in user
      redirect_to user
    else
      flash.now[:error] = 'Invalid email/password combination'
      render 'new'
    end
  end


  def destroy
    sign_out
    redirect_to root_path
  end
end

用户模型为:

class User < ActiveRecord::Base
  attr_accessible :email, :name, :nickname,:password, :password_confirmation 
  has_secure_password


  before_save { |user| user.email = email.downcase }
  before_save { |user| user.nickname = nickname.downcase }
  before_save :create_remember_token
....validations......

    private

    def create_remember_token
      self.remember_token = SecureRandom.urlsafe_base64
    end
end 

这是我的session.helper

module SessionsHelper

  def sign_in(user)
    cookies.permanent[:remember_token] = user.remember_token
    self.current_user = user
  end
  def signed_in?
    !current_user.nil?
  end

  def current_user=(user)
    @current_user = user
  end

  def current_user
    @current_user ||= User.find_by_remember_token(cookies[:remember_token])
  end

  def sign_out
    self.current_user = nil
    cookies.delete(:remember_token)
  end
end

我尝试了heroku rake db:migrate,heroku重新启动..没有变化。

ytsejam asked 2020-07-30T09:54:20Z
2个解决方案
80 votes

这意味着存储在has_secure_password中的哈希不是有效的BCrypt哈希(包括如果该字段为空)。

根据注释,您似乎只是在has_secure_password不在的时候创建了用户,所以密码摘要从未存储。 在数据库中查看,您可能会看到该用户的password_digest为空。 从数据库中删除该用户,然后使用新的工作代码重新创建,它应该可以工作。

虽然在评论中进行讨论,但是我(不正确)猜测密码为什么会出错,并且我已经写下了解释。 因此,这适用于确实有此问题的任何将来的访客,即使它不适用于此处:


当您从使用SHA1或其他算法切换到BCrypt但无法在BCrypt中重新散列密码时,通常会发生这种情况。 由于您无权访问原始密码(或者至少不应该...),因此切换起来有点麻烦,因为您必须同时使用BCrypt和原始身份验证方案。 例如,如果您以前使用SHA1,现在使用BCrypt,则必须将SHA1密码哈希视为BCrypt输入的纯文本密码。 例如,您可以这样创建一个BCrypt摘要:

sha1_password = Digest::SHA1.hexdigest("#{salt}#{real_password}")
self.password_digest = BCrypt::Password.create(sha1_password).to_s

然后,您可以根据您有权访问的sha1密码散列创建bcrypt password_digests。

您将像这样进行身份验证:

sha1_password = Digest::SHA1.hexdigest("#{salt}#{attempted_password}")
BCrypt::Password.new(self.password_digest) == sha1_password

我在上面的示例中使用了SHA1,但是它也适用于其他哈希算法。

Ben Lee answered 2020-07-30T09:55:04Z
11 votes

我已经有实时用户,并且同样已经将未加密的密码保存到数据库中。 一旦我开始使用bcrypt,它就会期待一个加密的密码,当找不到它时,就会产生此错误。

因此,我添加了此应急措施以捕获错误并提示旧用户重置其密码:

begin
    # your code that attempts to login the user
rescue BCrypt::Errors::InvalidHash
  flash[:error] = 'We recently adjusted the way our passwords are stored. Please click the "forgot username or password?" link to re-establish your password. Thank you for your understanding!'
  redirect_to password_resets_url
end 

希望这可以帮助。

nfriend21 answered 2020-07-30T09:55:33Z
translate from https://stackoverflow.com:/questions/11037864/bcrypterrorsinvalidhash-when-trying-to-sign-in