将纯文本密码与authenticate_or_request_with_http_digest一起使用
我在尝试快速启动并运行 HTTP Digest 身份验证时遇到了一些困难,这与指南中的建议非常相似:
Ruby on Rails 指南:操作控制器概述 > HTTP 摘要身份验证
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?我也对 any? 块如何工作感到有点困惑,这可能没有帮助:-/
就像快速说明:我知道我不应该真正以纯文本形式存储密码,并且在这样的源代码中。我只是想建立一个理解,稍后会重构它。
非常感谢您提前提供的所有帮助:-D
I've got myself a little stuck trying to get a quick bit of HTTP Digest authentication up and running, pretty much like suggested within the guide:
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
I get prompted for a username and password although when inputting the above the authentication seems to fail and I get prompted again. So I started to dig into the code that validates the request here:
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
I can't see how it is handling the password as plain text. How is password_is_ha1 being set? I'm also a little confused on how any? block is working which might not be helping :-/
Just as quick note: I know that I shouldn't really be storing passwords in plain text, and in source code like this. I'm just trying to build up an understanding and will refactor this later.
A massive thanks for all your help in advance :-D
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
any?
方法的行为类似于collect
,只不过它在其块第一次返回true
时返回true
。在这里,它的作用类似于数组[true, false]
上的循环:该块首先在
password_is_ha1
设置为true
的情况下运行。如果该块返回true
,any?
立即返回true
,并且由于这是validate_digest_response
的最后一条语句,该方法作为一个整体返回true
。否则,该块将再次运行,并将
password_is_ha1
设置为false
。如果该块返回true
,any?
立即返回true
,并且由于这是validate_digest_response
的最后一条语句,该方法作为一个整体返回true
。如果这两个运行都没有返回
true
,则any?
返回false
。由于这是validate_digest_response
的最后一个语句,因此该方法作为一个整体返回false
。因此,该行的作用是首先假设它是散列密码并检查它是否有效,然后假设它是明文密码并检查它是否有效。另一种更详细的写法是:
The
any?
method acts likecollect
, except it returnstrue
the first time its block returnstrue
. Here, it acts like a loop over the array[true, false]
:The block is first run with
password_is_ha1
set totrue
. If the block returnstrue
,any?
immediately returnstrue
, and since this is the last statement ofvalidate_digest_response
, the method as a whole returnstrue
.Otherwise, the block is run again with
password_is_ha1
set tofalse
. If the block returnstrue
,any?
immediately returnstrue
, and since this is the last statement ofvalidate_digest_response
, the method as a whole returnstrue
.If neither of those runs returned
true
,any?
returnsfalse
. Since this is the last statement ofvalidate_digest_response
, the method as a whole returnsfalse
.Thus, the effect of that line is to first assume it's a hashed password and check if it's valid, then assume it's a plaintext password and check if it's valid. Another, more verbose, way to write it would have been: