将纯文本密码与authenticate_or_request_with_http_digest一起使用

发布于 2024-12-05 11:25:25 字数 1978 浏览 0 评论 0原文

我在尝试快速启动并运行 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

半城柳色半声笛 2024-12-12 11:25:25

any? 方法的行为类似于 collect,只不过它在其块第一次返回 true 时返回 true。在这里,它的作用类似于数组 [true, false] 上的循环:

  1. 该块首先在 password_is_ha1 设置为 true 的情况下运行。如果该块返回 trueany? 立即返回 true,并且由于这是 validate_digest_response 的最后一条语句,该方法作为一个整体返回 true

  2. 否则,该块将再次运行,并将 password_is_ha1 设置为 false。如果该块返回 trueany? 立即返回 true,并且由于这是 validate_digest_response 的最后一条语句,该方法作为一个整体返回 true

  3. 如果这两个运行都没有返回 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

The any? method acts like collect, except it returns true the first time its block returns true. Here, it acts like a loop over the array [true, false]:

  1. The block is first run with password_is_ha1 set to true. If the block returns true, any? immediately returns true, and since this is the last statement of validate_digest_response, the method as a whole returns true.

  2. Otherwise, the block is run again with password_is_ha1 set to false. If the block returns true, any? immediately returns true, and since this is the last statement of validate_digest_response, the method as a whole returns true.

  3. If neither of those runs returned true, any? returns false. Since this is the last statement of validate_digest_response, the method as a whole returns false.

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:

   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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文