2013-04-04 74 views
2

我正在为基于HTTP摘要验证的用户验证用户的ruby应用程序创建一个API。我决定使用Grape API库,因为它使得在Ruby中创建一个API清理器。葡萄文档指出您可以使用摘要式身份验证,如:葡萄API和HTTP摘要验证

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

上面的葡萄实现是Rack::Auth::Digest::MD5

的包装现在也为安全,我读了如RFC 2617中你不需要存储密码为您存储用户名的MD5摘要数据库明文:境界:密码和authticate对抗,所以我创建了一个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 

现在用我提供什么,我失去了对如何连接这些t我并让它工作。

回答

3

不幸的是,Rack::Auth::Digest::MD5需要服务器端的明文密码。

葡萄示例代码显示了一个硬编码的密码查找。

您可以用

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

提供您存储明文密码Key类取代{ 'user1' => 'password1' }[username]。您可以存储这些可逆加密的我想,尽管这不会增加很多安全性,除非您为密钥管理构建相对复杂/昂贵的方案。

不知道是否有解决方法,让你存储散列密码。 MD5不是最安全的散列选择(虽然比没有好!)。如果安全性是您的API的重要关注点,那么您会希望超越摘要验证 - 例如,使用https可以提供帮助。

编辑:继位到往复讨论,葡萄的示例的以下变化允许你存储的密码MD5'd:

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 

你存储的Digest::MD5.hexdigest("#{username}:#{realm}:#{password}")在每个用户的密码属性的结果。

注意两次散列:realm两次。这有点冒险,但至少你不必编写自己的中间件,Grape仍然在处理它。这是而不是葡萄记录的功能或覆盖测试,所以可能无法在未来的版本。

+0

环顾四周后[机架文摘MD5(https://github.com/rack/rack/blob/master/lib/rack/auth/digest/md5.rb)我想通了,如果'attr_writer:passwords_hashed'设置为“真”,那么它将接受格式为'username:realm:password'的已经哈希密码,这很好,但即时通过Grape API封装器设置该属性有困难。有什么建议么? – ny95 2013-04-05 14:16:08

+0

通过查看葡萄码,您可以将哈希提供给':realm'符号,其中包含':realm,:opaque,:passwords_hashed'键。 。 。没有记录或在葡萄测试,所以有点后门你想要的。我测试了它,但它对我没有用。 – 2013-04-05 15:03:29

+0

我想去尝试一下,看看会发生什么,对于不透明的值,它是什么意思,我可以将它设置为“SecureRandom.hex(15)”吗? – ny95 2013-04-05 15:10:57