我正在为我的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/