1. ホーム
  2. ruby-on-rails

[解決済み] Railsです。サインイン時に "BCrypt::Errors::InvalidHash" が発生する

2022-02-16 20:21:32

質問

私はあるプロジェクトを完成させようとしています。私はユーザーモデルを使用しています。 私はサインアップするとき、すべてがうまく見える。しかし、私は同じメンバーにサインインしようとすると、このエラーが発生します。

申し訳ありませんが、何か問題が発生しました。 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 

これは私の セッション・ヘルパー

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 restart...を試しましたが、変化がありません。

どうすればいいですか?

これは password_digest は有効な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

次に、bcrypt password_digests を作成するには、以下のように sha1 パスワードハッシュを元にします。 する にアクセスすることができます。

このように認証することになる。

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

上記の例ではSHA1を使用しましたが、これは他のハッシュアルゴリズムでも同様に動作します。