我有点陷入困境,试图快速启动并运行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
答案 0 :(得分:0)
any?
方法的行为与collect
类似,只是在其第一次返回true
时返回true
。在这里,它就像一个数组[true, false]
上的循环:
首先运行该区块,password_is_ha1
设置为true
。如果块返回true
,any?
会立即返回true
,因为这是validate_digest_response
的最后一个语句,整个方法将返回true
。< / p>
否则,再次运行该块,password_is_ha1
设置为false
。如果块返回true
,any?
会立即返回true
,因为这是validate_digest_response
的最后一个语句,整个方法将返回true
。< / p>
如果这些运行都没有返回true
,则any?
会返回false
。由于这是validate_digest_response
的最后一个语句,因此整个方法返回false
。
因此,该行的效果是首先假设它是一个哈希密码并检查它是否有效,然后假设它是一个明文密码并检查它是否有效。编写它的另一种更详细的方法是:
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