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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11037864/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 03:32:26  来源:igfitidea点击:

"BCrypt::Errors::InvalidHash" when trying to sign in

ruby-on-railsherokubcrypt

提问by ytsejam

I am trying to finish a project. I am working with user models. When I signup everything seems ok . But when I try to signin the same member I get this error.

我正在努力完成一个项目。我正在使用用户模型。当我注册时一切正常。但是当我尝试登录同一个成员时,我收到此错误。

We're sorry, but something went wrong. heroku logsfile shows error as:

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

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

my *sessions_controller*is :

我的*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

and user modelis :

用户模型是:

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 

this is my session.helper

这是我的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

I tried heroku rake db:migrate, heroku restart.. there is no change.

我试过 heroku rake db:migrate, heroku restart .. 没有变化。

回答by Ben Lee

This means that the hash stored in password_digestis not a valid BCrypt hash (including if the field is empty).

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

Based on the comments, it looks like you just created the user at a time the has_secure_passwordwasn't there, so the password digest never got stored. Look in the database, you'll probably see that password_digestis empty for that user. Remove the user from the database and re-create with your new working code and it should work.

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

While discussing with in the comments though, I made an (incorrect) guess about why the passwords would be wrong, and I already wrote up the explanation. So here it is for any future visitor that does have this problem, even though it doesn't apply directly here:

虽然在评论中讨论,但我对密码错误的原因进行了(不正确的)猜测,并且我已经写下了解释。因此,这里适用于确实有此问题的任何未来访问者,即使它不直接适用于此处:



This typically happens when you switch from using SHA1 or another algorithm to BCrypt but fail to re-hash the passwords in BCrypt. Since you don't have access to the original passwords (or at least you shouldn't...), it's a bit ugly to switch because you have to use bothBCrypt and the original authentication scheme. For example, if you were using SHA1 before and now use BCrypt, you have to treat the SHA1 password hash asthe plain text password for BCrypt input. For example, you might create a BCrypt digest like this:

当您从使用 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

Then, you can create bcrypt password_digests based on the sha1 password hashes that you dohave access to.

然后,您可以创建基于SHA-1密码哈希bcrypt password_digests你访问。

You would authenticate like this:

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

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

I used SHA1 in the above examples, but this will work for other hashing algorithms as well.

我在上面的例子中使用了 SHA1,但这也适用于其他散列算法。

回答by nfriend21

I already had live users, and likewise already saved unencrypted passwords into the database. Once I started using bcrypt, it was expecting an encrypted password, and when it didn't find it, it produced this error.

我已经有在线用户,同样已经将未加密的密码保存到数据库中。一旦我开始使用 bcrypt,它就期待一个加密的密码,当它没有找到它时,它产生了这个错误。

Therefore, I added this rescue to catch the error and prompt the legacy users to reset their password:

因此,我添加了这个救援来捕捉错误并提示旧用户重置他们的密码:

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 

Hope this helps.

希望这可以帮助。