代码之家  ›  专栏  ›  技术社区  ›  ny95

葡萄API和HTTP摘要认证

  •  2
  • ny95  · 技术社区  · 11 年前

    我正在为我的ruby应用程序创建一个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开始,你不需要将密码以明文形式存储在数据库中,你可以存储用户名的MD5摘要:realm:password并对此进行验证,所以我创建了一个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
    

    现在,对于我所提供的,我不知道如何将这两者联系起来并使其发挥作用。

    1 回复  |  直到 11 年前
        1
  •  3
  •   Neil Slater    11 年前

    不幸地 Rack::Auth::Digest::MD5 在服务器端需要一个明文密码。

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

    你可以更换 { 'user1' => 'password1' }[username] 具有

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

    如果你储存了 明文 中的密码 Key 班我想,你可以存储这些可逆加密的密钥,尽管这不会增加太多安全性,除非你构建相对复杂/昂贵的密钥管理方案。

    不确定是否有办法让你存储散列密码。MD5并不是最安全的哈希选择(尽管总比什么都没有好!)。如果安全性是API的一个重要问题,那么您需要超越摘要身份验证,例如,使用https会有所帮助。

    编辑:经过一些来回的讨论,下面是葡萄的例子 允许您存储MD5密码:

    auth :http_digest, { :realm => { :realm => 'Llama', :passwords_hashed => true, :opaque => "7302c32d39bbacb5ed0ace096723fd" } } do |username|
      Digest::MD5.hexdigest( 'fred:Llama:654321' )
    end
    

    该示例给出了一个硬编码的用户名:“red”,密码:“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仍在处理它 Grape的一个文档化功能或包含了测试,因此可能在未来的版本中不起作用。