使用明文密码与authenticate_or_request_with_http_digest

时间:2011-09-17 13:21:59

标签: ruby-on-rails ruby authentication ruby-on-rails-3.1 http-digest

我有点陷入困境,试图快速启动并运行HTTP Digest身份验证,非常类似于指南中的建议:

Ruby on Rails Guides: Action Controller Overview > HTTP Digest Authentication

class ApplicationController < ActionController::Base
  protect_from_forgery

  USERS = { "sam" => "ruby" }

  before_filter :authenticate

private
  def authenticate
    authenticate_or_request_with_http_digest do |username|
      USERS[username]
    end
  end
end

我收到提示输入用户名和密码,但输入上述内容时,身份验证似乎失败,我再次收到提示。所以我开始深入研究验证请求的代码:

GitHub: http_authentication.rb > validate_digest_response

  def validate_digest_response(request, realm, &password_procedure)
    secret_key  = secret_token(request)
    credentials = decode_credentials_header(request)
    valid_nonce = validate_nonce(secret_key, request, credentials[:nonce])

    if valid_nonce && realm == credentials[:realm] && opaque(secret_key) == credentials[:opaque]
      password = password_procedure.call(credentials[:username])
      return false unless password

      method = request.env['rack.methodoverride.original_method'] || request.env['REQUEST_METHOD']
      uri    = credentials[:uri][0,1] == '/' ? request.fullpath : request.url

     [true, false].any? do |password_is_ha1|
       expected = expected_response(method, uri, credentials, password, password_is_ha1)
       expected == credentials[:response]
     end
    end
  end

我无法看到它如何以纯文本形式处理密码。如何设置 password_is_ha1 ?我对任何?块的工作方式也有点困惑,这可能没有帮助: - /

同样快速注意:我知道我不应该用纯文本和像这样的源代码存储密码。我只是想建立一种理解,稍后会重构它。

非常感谢你提前帮助:-D

1 个答案:

答案 0 :(得分:0)

any?方法的行为与collect类似,只是在其第一次返回true时返回true。在这里,它就像一个数组[true, false]上的循环:

  1. 首先运行该区块,password_is_ha1设置为true。如果块返回trueany?会立即返回true,因为这是validate_digest_response的最后一个语句,整个方法将返回true。< / p>

  2. 否则,再次运行该块,password_is_ha1设置为false。如果块返回trueany?会立即返回true,因为这是validate_digest_response的最后一个语句,整个方法将返回true。< / p>

  3. 如果这些运行都没有返回true,则any?会返回false。由于这是validate_digest_response的最后一个语句,因此整个方法返回false

  4. 因此,该行的效果是首先假设它是一个哈希密码并检查它是否有效,然后假设它是一个明文密码并检查它是否有效。编写它的另一种更详细的方法是:

       expected = expected_response(method, uri, credentials, password, true)
       return true if expected == credentials[:response]
    
       expected = expected_response(method, uri, credentials, password, false)
       return true if expected == credentials[:response]
    
       return false