简体   繁体   English

无法使用BCrypt在Rails上进行身份验证-密码哈希不同

[英]Can't authenticate on Rails with BCrypt - password hashes are different

I am trying to create a simple authentication system but I seem to have a problem. 我正在尝试创建一个简单的身份验证系统,但似乎有问题。

The signup process works fine, but when I try to login with the exact same information, I can't (I get "Invalid email or password"). 注册过程工作正常,但是当我尝试使用完全相同的信息登录时,我不能(我收到“无效的电子邮件或密码”)。 As I saw, the hash comparison returns false. 如我所见,哈希比较返回false。 Here is my code: 这是我的代码:

#sessions_controller.rb

def create
  user = User.authenticate(params[:email], params[:password])
  if user
    session[:user_id] = user.id
    redirect_to root_url, :notice => "Logged in!"
  else
    flash.now.alert = "Invalid email or password"
    render "new"
  end
end

and

class User < ActiveRecord::Base
attr_accessor :password
before_save :encrypt_password

validates_confirmation_of :password
validates_presence_of :password, :on => :create
validates_presence_of :name
validates_presence_of :email
validates_uniqueness_of :email

def self.authenticate(email, password)
  user = User.where(email: email).first
  # throw Exception.new(user.password_hash) #uncaught throw #<Exception: $2a$10$9FHhPyb7BW01ktwTTgZHX.hlKKv4ajX/dX9D/xNGmZoajJTdGG4N.>
  # throw Exception.new(user.password_salt) #uncaught throw #<Exception: $2a$10$9FHhPyb7BW01ktwTTgZHX.>
  # throw Exception.new(BCrypt::Engine.hash_secret(password, user.password_salt)) #uncaught throw #<Exception: $2a$10$9FHhPyb7BW01ktwTTgZHX.O62xalJit020Jb0g5XDdB5V8dGMslQS>
  if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
    user
  else
    nil
  end
end

def encrypt_password
  if password.present?
    self.password_salt = BCrypt::Engine.generate_salt
    self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
  end
end
end

So, as you can see in the commented lines in user.rb, the password hash that I get when trying to log in is not the same with the original one. 因此,正如您可以在user.rb的注释行中看到的那样,尝试登录时得到的密码哈希与原始密码不同。 Obviously, the password I enter is the correct one. 显然,我输入的密码是正确的。

user.password_hash = $2a$10$9FHhPyb7BW01ktwTTgZHX.hlKKv4ajX/dX9D/xNGmZoajJTdGG4N.
user.password_salt = $2a$10$9FHhPyb7BW01ktwTTgZHX.
BCrypt::Engine.hash_secret(password, user.password_salt) = $2a$10$9FHhPyb7BW01ktwTTgZHX.O62xalJit020Jb0g5XDdB5V8dGMslQS

Can you please give me a hint here? 你能在这里给我一个提示吗? What is that I do wrong? 我做错了什么?

Thanks a lot! 非常感谢!


//later edit: also adding the users controller, perhaps this can help. //稍后编辑:还添加了用户控制器,也许可以帮上忙。

class UsersController < ApplicationController

  def new
    @user = User.new(user_params)
  end

  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to root_url, :notice => "Signed up!"
    else
      render "new"
    end   
  end

  private
    def user_params
      params.fetch(:user).permit(:name, :email, :password, :password_confirmation) if params[:user]
    end

end

Edit: posting the logs for signing up/logging in 编辑:发布用于注册/登录的日志

Started GET "/sign_up" for 127.0.0.1 at 2013-10-11 11:23:13 +0300
Processing by UsersController#new as HTML
  Rendered users/new.html.erb within layouts/application (31.8ms)
Completed 200 OK in 48ms (Views: 41.8ms | ActiveRecord: 1.2ms)


Started POST "/users" for 127.0.0.1 at 2013-10-11 11:24:30 +0300
Processing by UsersController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"LPLEs9at6BLGgjikYynnEzA/JAMMVl9IYGId1zEyNEg=", "user"=>{"name"=>"johntest", "email"=>"johntest@johntest.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Create User"}
   (0.1ms)  BEGIN
  User Exists (0.4ms)  SELECT 1 AS one FROM `users` WHERE `users`.`email` = BINARY 'johntest@johntest.com' LIMIT 1
  SQL (0.3ms)  INSERT INTO `users` (`created_at`, `email`, `name`, `password_hash`, `password_salt`, `updated_at`) VALUES ('2013-10-11 08:24:30', 'johntest@johntest.com', 'johntest', '$2a$10$tpDFvkFUC.OPckDm6xacU.xkjFmECg2CDpsi3cjTJNX6K58ujHOn6', '$2a$10$tpDFvkFUC.OPckDm6xacU.', '2013-10-11 08:24:30')
   (39.2ms)  COMMIT
Redirected to http://localhost:3000/
Completed 302 Found in 141ms (ActiveRecord: 40.0ms)

Started GET "/" for 127.0.0.1 at 2013-10-11 11:24:30 +0300
Processing by TroublesController#frontpage as HTML
  Trouble Load (0.2ms)  SELECT `troubles`.* FROM `troubles`
  CACHE (0.0ms)  SELECT `troubles`.* FROM `troubles`
  Rendered troubles/_marker_infowindow.html.erb (0.8ms)
  Rendered troubles/_marker_infowindow.html.erb (0.1ms)
  Rendered /home/alex/.rvm/gems/ruby-2.0.0-p247/gems/gmaps4rails-1.5.6/app/views/gmaps4rails/_gmaps4rails.html.erb (1.9ms)
  Rendered troubles/frontpage.html.erb within layouts/application (3.9ms)
Completed 200 OK in 21ms (Views: 13.5ms | ActiveRecord: 0.2ms)

[...](loading assets)

Started GET "/log_in" for 127.0.0.1 at 2013-10-11 11:24:52 +0300
Processing by SessionsController#new as HTML
  Rendered sessions/new.html.erb within layouts/application (1.1ms)
Completed 200 OK in 14ms (Views: 12.8ms | ActiveRecord: 0.0ms)


Started POST "/sessions" for 127.0.0.1 at 2013-10-11 11:25:05 +0300
Processing by SessionsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"LPLEs9at6BLGgjikYynnEzA/JAMMVl9IYGId1zEyNEg=", "name"=>"johntest", "email"=>"johntest@johntest.com", "password"=>"[FILTERED]", "commit"=>"Log in"}
  User Load (0.4ms)  SELECT `users`.* FROM `users` WHERE `users`.`email` = 'johntest@johntest.com' ORDER BY `users`.`id` ASC LIMIT 1
  Rendered sessions/new.html.erb within layouts/application (1.7ms)
Completed 200 OK in 99ms (Views: 10.9ms | ActiveRecord: 0.4ms)

[...](loading assets)

So I went to the sign up page, filled in the details, I was forwarded to the homepage and it said "Signed up!". 因此,我进入了注册页面,填写了详细信息,我被转发到主页,并显示“ Signed up!”。 I clicked login, entered the details and it says "Invalid email or password". 我单击登录,输入详细信息,并显示“无效的电子邮件或密码”。

Bcrypt is decrypting the right way but the culprit in your code is the before_save :encrypt_password just change the before save event as before_create event. Bcrypt正在以正确的方式解密,但是代码中的罪魁祸首是before_save:encrypt_password只是将之前的保存事件更改为before_create事件。 with before_save , Every time you update the user record encrypt_password is called and it is encrypting the password field that way you are losing the first encrypted password which never matches though you give the correct password. 使用before_save,每次更新用户记录时,都会调用一次crypto_password记录,并且正在加密密码字段,这样您将丢失第一个加密密码,尽管您提供了正确的密码却从未匹配过。 I got stuck up with the same issue, after a deep analysis I got to know the fix. 经过深入分析后,我陷入了同样的问题,我知道了解决方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM