2012-06-14 2 views
37

Sto provando a completare un progetto. Sto lavorando con i modelli utente. Quando mi iscrivo tutto sembra ok. Ma quando provo ad accedere allo stesso utente, ottengo questo errore."BCrypt :: Errors :: InvalidHash" quando si prova ad accedere

Siamo spiacenti, ma qualcosa è andato storto. log Heroku di file mostra errore come:

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

mia * 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 

e utente modello è:

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 

questo è il mio 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 

ho cercato Heroku rake db: migrate, Heroku riavvio .. non c'è alcun cambiamento.

+1

puoi mostrarci il tuo metodo 'sign_in'? –

+0

Modificato il mio primo messaggio con session.helper nel messaggio.è il metodo sign_in – ytsejam

+0

Nel caso in cui sia stato eseguito il comando 'bundle install' con' gem 'bcrypt-ruby', '3.0.1'' nel tuo 'Gemfile' ? –

risposta

67

Ciò significa che l'hash memorizzato in password_digest non è un hash BCrypt valido (incluso se il campo è vuoto).

In base ai commenti, sembra che tu abbia appena creato l'utente in un momento in cui lo has_secure_password non era presente, quindi il digest della password non è stato memorizzato. Cerca nel database, probabilmente vedrai che password_digest è vuoto per quell'utente. Rimuovere l'utente dal database e ricreare con il nuovo codice funzionante e dovrebbe funzionare.

Mentre discutevo con i commenti, ho fatto un'ipotesi (errata) sul perché le password sarebbero state sbagliate, e ho già scritto la spiegazione. Così qui è per ogni futuro visitatore che ha questo problema, anche se essa non si applica direttamente qui:


Questo accade in genere quando si passa da utilizzare SHA1 o di un altro algoritmo per bcrypt ma non riescono a ri- hash le password in BCrypt. Dato che non hai accesso alle password originali (o almeno non dovresti ...), è un po 'brutto passare perché devi usare sia BCrypt sia lo schema di autenticazione originale. Ad esempio, se si utilizza SHA1 prima e ora si utilizza BCrypt, è necessario considerare l'hash della password SHA1 come la password di testo semplice per l'input BCrypt. Ad esempio, è possibile creare una bcrypt digerire come questo:

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

Quindi, è possibile creare password_digests bcrypt sulla base della password SHA1 hash che si fare hanno accesso.

Si potrebbe autenticarsi in questo modo:

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

ho usato SHA1 negli esempi precedenti, ma questo lavoro per altri algoritmi di hashing pure.

+0

Ben Lee ringrazia. ora funziona. mi hai salvato il giorno e la notte. – ytsejam

+0

@ytsejam, felice di aiutare –

+0

stavo cercando per ore, grazie mille! – Linus

9

Ho già avuto utenti dal vivo e ho già salvato password non crittografate nel database. Una volta iniziato a utilizzare bcrypt, mi aspettavo una password crittografata e, quando non la trova, ha generato questo errore.

Pertanto, ho aggiunto questo salvataggio per catturare l'errore e richiederà agli utenti legacy per reimpostare la 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 

Spero che questo aiuti.

+1

Non penso che sia una buona idea affidarsi a authenticate() che genera un'eccezione non documentata; è più semplice aggirarlo controllando password_digest.empty? prima di chiamare authenticate(). – pdg137

+0

Ho anche utenti esistenti (anche se un piccolo set). Ho aggiornato manualmente le password con 'u = User.find (...); u.password = ""; u.save! 'e ha inviato a tutti le nuove password. Il punto qui suppongo è che semplicemente aggiornando la password tramite il modello, set tutto correttamente. –

+1

ha funzionato per me grazie –