Ruby и Sinatra не могут сравнить хешированный пароль с BCrypt

Я разрабатываю простое приложение для аутентификации Ruby с помощью Sinatra и DataMapper.

Я успешно реализовал метод хеширования пароля, когда пользователи регистрируются, но я не могу заставить маршрут аутентификации работать, он просто не соответствует предоставленному паролю с хешированной версией, хранящейся в БД (MySQL).

После прочтения большого количества документации, множества вопросов здесь, посвященных stackoverflow, и повторной документации, я прошу вашей помощи.

Я создал простой маршрут GET, чтобы попытаться понять, как работает библиотека BCrypt, без сохранения пароля в БД, цель этого маршрута — просто понять, как использовать библиотеку:

get "/test" do
  password_hash = BCrypt::Password.create("wazz")
  password = "wazz"
  puts password_hash
  if BCrypt::Password.new(password_hash).is_password? password
    status 201
  end
  halt(500, {error: password_hash}.to_json)
end

Итак, в основном все, что мне нужно сделать, это отправить запрос GET в /test, и все должно быть сделано, но это не так, BCrypt::Password.new, похоже, не проверяет исходный пароль на соответствие хешированному.

Заранее спасибо, любая помощь будет очень признательна.


person Alex Anghelone    schedule 12.03.2015    source источник
comment
Я не вижу ничего плохого в вашем коде, и если я вырезаю и вставляю первую часть в IRB, у меня это работает. Не могли бы вы дать более подробную информацию о том, что означает все, что должно быть сделано, то есть что вы ожидаете от своего фрагмента кода и как вы его тестируете? Что на самом деле происходит? NB вы также можете использовать password_hash.is_password?( password ) в качестве теста   -  person Neil Slater    schedule 12.03.2015
comment
О, подождите, когда пароль совпадает, вы вызываете status 201, затем останавливаетесь со статусом, установленным обратно на 500 . . . поэтому этот код всегда останавливается с ошибкой сервера, независимо от того, что случилось с паролем. В bcrypt нет ничего плохого, просто вам нужно инвертировать логику в маршруте Sinatra.   -  person Neil Slater    schedule 12.03.2015
comment
Что я ожидаю, так это то, что если отправить запрос GET на маршрут /test, он сгенерирует хэш пароля wazz, а затем сравнит хэш с исходным паролем, дав мне статус 201.   -  person Alex Anghelone    schedule 12.03.2015
comment
Спасибо, Нил, я знал, что решение было у меня перед носом, и я его не видел :) Я изменил код, перемещающий остановку внутри оператора else, на if password_hash.is_password?( пароль ). Большое спасибо, теперь это работает.   -  person Alex Anghelone    schedule 12.03.2015


Ответы (1)


Ваше использование bcrypt работает, но поток программы неверен. Самое главное, вызов status 201 не выходит из контроллера в этот момент, он продолжается, поэтому вы настроили все так, что работает bcrypt или нет, не имеет значения.

Вместо этого сделайте что-то вроде этого:

get "/test" do
  password_hash = BCrypt::Password.create("wazz")
  password = "wazz"

  unless BCrypt::Password.new(password_hash).is_password? password
    halt(500, {error: password_hash}.to_json)
  end

  status 201
  {message: 'Session created'}.to_json
end
person Neil Slater    schedule 12.03.2015
comment
Спасибо, Нил, я не могу проголосовать из-за своей низкой репутации, но ты это заслужил :) - person Alex Anghelone; 12.03.2015