我正在为我的ruby应用程序创建一个api,该api基于http摘要身份验证对用户进行身份验证。我决定使用grape api库,因为它使用ruby创建api变得更干净。grape文档说明您可以使用摘要式身份验证,如:

http_digest({ :realm => 'Test Api', :opaque => 'app secret' }) do |username|
  # lookup the user's password here
  { 'user1' => 'password1' }[username]
end

上面的grape实现是Rack::Auth::Digest::MD5
现在为了安全起见,我读到,从rfc 2617开始,您不需要在数据库中将密码存储为纯文本,而是存储用户名:realm:password和authenticate的md5摘要,因此我创建了一个datamapper模型:
class Key
  include DataMapper::Resource

  property :id,              Serial

  property :username,        String
  property :password,        String

  property :active,          Boolean, :default => true
  property :created_at,      DateTime, :default => DateTime.now
  property :updated_at,      DateTime
end

现在,根据我所提供的,我迷失了如何将这两者联系起来并使之发挥作用。

最佳答案

不幸的是,Rack::Auth::Digest::MD5在服务器端需要明文密码。
grape示例代码显示了一个硬编码的密码查找。
你可以用

Key.first( :username => username ).password

前提是您将明文密码存储在{ 'user1' => 'password1' }[username]类中。我想您可以存储这些可逆加密的密钥,尽管除非您构建相对复杂/昂贵的密钥管理方案,否则这不会增加多少安全性。
不确定是否有办法让您存储散列密码。MD5并不是最安全的哈希选择(尽管比什么都没有要好!)。如果安全性是您的API的一个重要关注点,那么您将希望超越摘要式身份验证,例如,使用https将有所帮助。
编辑:在讨论中来回地进行一些讨论之后,grape示例的以下变体允许您存储md5的密码:
auth :http_digest, { :realm => { :realm => 'Llama', :passwords_hashed => true, :opaque => "7302c32d39bbacb5ed0ace096723fd" } } do |username|
  Digest::MD5.hexdigest( 'fred:Llama:654321' )
end

这个例子给出了一个硬编码的用户名:“fred”,密码:“654321”响应。所以我认为你的目标代码是:
auth :http_digest, { :realm => { :realm => 'Llama', :passwords_hashed => true, :opaque => "7302c32d39bbacb5ed0ace096723fd" } } do |username|
  k = Key.first( :username => username )
  k ? k.password : nil
end

并将Key的结果存储在每个用户的密码属性中。
注意两次Digest::MD5.hexdigest( "#{username}:#{realm}:#{password}" )的双层散列。这有点老套,但至少你不必编写自己的中间件,grape仍在处理它。这不是grape的一个文档化特性,也没有被测试覆盖,因此在将来的版本中可能不起作用。

关于ruby - Grape API和HTTP摘要认证,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15822593/

10-08 23:07