Ruby和Sinatra,无法使用BCrypt比较哈希密码

3

我正在使用Sinatra和DataMapper开发一个简单的Ruby身份验证应用。

当用户注册时,我已经成功实现了一种哈希密码方法,但是我无法让身份验证路由正常工作,它只是无法将提供的密码与存储在数据库(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

基本上,我所要做的就是向/test发送一个GET请求,一切都应该完成了,但实际上并没有。 BCrypt::Password.new似乎不能将原始密码与哈希密码进行验证。
提前感谢您的帮助,非常感激。

我看不出你的代码有什么问题,如果我将第一部分剪切并粘贴到IRB中,它对我有效。你能否提供更多细节 - “all should be done”是什么意思,即你期望你的代码片段发生什么,以及你如何测试它?实际上会发生什么?注意,你也可以将password_hash.is_password?( password )作为测试。 - Neil Slater
哦,等一下,当密码匹配成功时,你调用 status 201,然后停止并将状态设置回 500……所以这段代码总是以服务器错误终止,无论密码发生了什么。bcrypt 没有问题,只是你需要在 Sinatra 路由中反转逻辑。 - Neil Slater
我期望发出一个GET请求到/test路由时,它将生成"wazz"密码的哈希值,然后将哈希值与原始密码进行比较,给我返回201状态。 - Axel Fooley
谢谢Neil,我知道解决方案就在我的眼前,但我没有看到它 :) 我改变了代码,将停止命令移动到“if password_hash.is_password?(password)”的“else”语句中。非常感谢,现在它可以工作了。 - Axel Fooley
1个回答

2

您使用的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

谢谢你,Neil。由于我的声望不高,我无法点赞,但你值得拥有它 :) - Axel Fooley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接