2012-06-14 34 views
37

Tôi đang cố hoàn thành một dự án. Tôi đang làm việc với các mô hình người dùng. Khi tôi đăng ký mọi thứ có vẻ ổn. Nhưng khi tôi cố gắng để đăng nhập cùng một thành viên tôi nhận được lỗi này."BCrypt :: Errors :: InvalidHash" khi cố gắng đăng nhập

Chúng tôi rất tiếc, nhưng đã xảy ra sự cố. bản ghi Heroku tập tin cho thấy lỗi như:

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

tôi * sessions_controller * là:

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 

sử dụng mô hình là:

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 

đây là của tôi 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 

Tôi đã thử heroku rake db: migrate, heroku restart .. không có thay đổi.

+1

bạn có thể hiển thị cho chúng tôi phương thức 'sign_in' của bạn không? –

+0

Đã chỉnh sửa thông điệp đầu tiên của tôi với session.helper trong thư.there là phương thức sign_in – ytsejam

+0

Chỉ trong trường hợp, bạn đã thực hiện 'bundle install' với' gem 'bcrypt-ruby', '3.0.1'' trong 'Gemfile' của bạn ? –

Trả lời

67

Điều này có nghĩa là mã băm được lưu trữ trong password_digest không phải là băm BCrypt hợp lệ (bao gồm cả trường trống).

Dựa trên nhận xét, có vẻ như bạn vừa tạo người dùng tại một thời điểm has_secure_password không có ở đó, do đó, mật khẩu không bao giờ được lưu trữ. Nhìn vào cơ sở dữ liệu, bạn có thể thấy rằng password_digest trống cho người dùng đó. Xóa người dùng khỏi cơ sở dữ liệu và tạo lại bằng mã làm việc mới của bạn và nó sẽ hoạt động.

Mặc dù đã thảo luận trong các nhận xét, tôi đã đoán (sai) về lý do mật khẩu sẽ sai và tôi đã viết giải thích. Vì vậy, ở đây nó là dành cho bất kỳ khách truy cập trong tương lai mà không có vấn đề này, mặc dù nó không áp dụng trực tiếp ở đây:


này thường xảy ra khi bạn chuyển từ việc sử dụng SHA1 này hay cách khác thuật toán để bcrypt nhưng thất bại trong việc tái băm mật khẩu trong BCrypt. Vì bạn không có quyền truy cập vào mật khẩu ban đầu (hoặc ít nhất bạn không nên ...), có chút xấu xí khi chuyển đổi vì bạn phải sử dụng cả hai BCrypt và lược đồ xác thực ban đầu. Ví dụ: nếu bạn đang sử dụng SHA1 trước và bây giờ sử dụng BCrypt, bạn phải xử lý mật khẩu SHA1 băm làm mật khẩu thuần văn bản cho đầu vào BCrypt. Ví dụ, bạn có thể tạo một bcrypt tiêu hóa như thế này:

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

Sau đó, bạn có thể tạo password_digests bcrypt dựa trên mật khẩu sha1 băm mà bạn làm có quyền truy cập vào.

Bạn sẽ xác thực như thế này:

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

tôi đã sử dụng SHA1 trong các ví dụ trên, nhưng điều này sẽ làm việc cho các thuật toán băm khác nữa.

+0

Ben Lee cảm ơn. bây giờ nó hoạt động. bạn đã cứu cả ngày lẫn đêm của tôi. – ytsejam

+0

@ytsejam, vui mừng được giúp đỡ –

+0

Tôi đã tìm kiếm hàng giờ, cảm ơn bạn rất nhiều! – Linus

9

Tôi đã có người dùng trực tiếp và tương tự như vậy đã lưu mật khẩu không được mã hóa vào cơ sở dữ liệu. Khi tôi bắt đầu sử dụng bcrypt, nó đã mong đợi một mật khẩu được mã hóa, và khi nó không tìm thấy nó, nó tạo ra lỗi này.

Vì vậy, tôi đã thêm giải cứu này để bắt lỗi và nhắc nhở người sử dụng di sản để thiết lập lại mật khẩu của họ:

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.

+1

Tôi không nghĩ rằng nên dựa vào việc xác thực() nâng cao một ngoại lệ không có giấy tờ; nó sạch hơn để làm việc xung quanh nó bằng cách kiểm tra password_digest.empty? trước khi gọi xác thực(). – pdg137

+0

Tôi cũng có người dùng hiện tại (mặc dù một bộ nhỏ). Tôi đã cập nhật mật khẩu theo cách thủ công bằng 'u = User.find (...); u.password = ""; u.save! 'và gửi cho mọi người mật khẩu mới. Điểm ở đây tôi đoán là chỉ cần cập nhật mật khẩu thông qua mô hình, thiết lập mọi thứ đúng cách. –

+1

đã làm việc cho tôi cảm ơn –

Các vấn đề liên quan