2012-06-14 18 views
37

Próbuję ukończyć projekt. Pracuję z modelami użytkowników. Kiedy się zapisuję, wszystko wydaje się w porządku. Ale kiedy próbuję zalogować się do tego samego członka, otrzymuję ten błąd."BCrypt :: Errors :: InvalidHash" podczas próby zalogowania się

Przykro nam, ale coś poszło nie tak. kłody Heroku plik pokazuje błąd jak:

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

mój * sessions_controller * jest:

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 

i użytkownik modelu jest:

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 

to moja 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 

Próbowałem Heroku rake db: migrować, Heroku restart .. nie ma zmian.

+1

czy możesz pokazać nam swoją metodę 'sign_in'? –

+0

Edytowałem moją pierwszą wiadomość z session.helper w message.there jest metoda sign_in – ytsejam

+0

Na wszelki wypadek, zrobiłeś 'bundle install' z' gem 'bcrypt-ruby', '3.0.1'' w twoim 'Gemfile' ? –

Odpowiedz

67

Oznacza to, że hash zapisany w password_digest nie jest prawidłowym hashem szyfrowania (w tym, jeśli pole jest puste).

Na podstawie komentarzy wygląda na to, że właśnie utworzono użytkownika w momencie, gdy nie było tam has_secure_password, więc hasło do hasła nigdy nie zostało zapisane. Poszukaj w bazie danych, prawdopodobnie zobaczysz, że password_digest jest pusty dla tego użytkownika. Usuń użytkownika z bazy danych i ponownie utwórz go przy użyciu nowego działającego kodu, który powinien działać.

Podczas dyskusji w komentarzach, zrobiłem (niepoprawne) domyślać się, dlaczego hasła byłyby błędne, a ja już napisałem wyjaśnienie. Więc to jest dla każdego przyszłego użytkownika, który ma tego problemu, choć nie dotyczy bezpośrednio tutaj:


Zazwyczaj zdarza się to podczas przełączania z użyciem SHA1 lub inny algorytm BCrypt ale nie ponownie hash hasła w BCrypt. Ponieważ nie masz dostępu do oryginalnych haseł (lub przynajmniej nie powinieneś ...), zmiana ustawień jest nieco brzydka, ponieważ musisz użyć zarówno BCrypt jak i oryginalnego schematu uwierzytelniania. Na przykład, jeśli używasz SHA1 przed i teraz używasz BCrypt, musisz traktować hasło SHA1 hash jako hasło zwykłego tekstu do wejścia BCrypt. Na przykład, można utworzyć BCrypt strawienia tak:

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

Następnie można tworzyć bcrypt password_digests oparciu o hasło SHA1 hash że zrobić mieć dostęp.

Można by uwierzytelnić tak:

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

użyłem SHA1 w powyższych przykładach, ale to będzie działać dla innych algorytmów mieszaja również.

+0

Ben Lee dzięki. teraz działa. Uratowałeś mi dzień i noc. – ytsejam

+0

@ytsejam, z przyjemnością pomogę –

+0

Szukałem godzin, dziękuję bardzo! – Linus

9

Już miałem użytkowników na żywo, a także już zapisane niezaszyfrowane hasła do bazy danych. Kiedy zacząłem używać bcrypt, spodziewałem się zaszyfrowanego hasła, a gdy go nie znalazłem, spowodowało to błąd.

Dlatego dodałem ten ratowanie złapać błąd i skłonić użytkowników starszych, aby zresetować swoje hasło:

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 

nadzieję, że to pomaga.

+1

Nie wydaje mi się, że warto polegać na authenticate() podnosząc nieudokumentowany wyjątek; jest czystsze, aby obejść go, sprawdzając password_digest.empty? przed wywołaniem authenticate(). – pdg137

+0

Mam również istniejących użytkowników (choć niewielki zestaw). Ręcznie zaktualizowałem hasła za pomocą 'u = User.find (...); u.password = ""; u.save! 'i wysłał wszystkim nowe hasła. Chodzi tutaj o to, że po prostu aktualizacja hasła za pośrednictwem modelu, ustawia wszystko poprawnie. –

+1

pracował dla mnie dzięki –

Powiązane problemy