0

ガイド内で提案されているように、HTTPダイジェスト認証を簡単に起動して実行しようとして、少し行き詰まりました。

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はどのように設定されていますか? 私も少し混乱しています。ブロックは機能していますが、役に立たない可能性があります:-/

簡単なメモ: パスワードを平文で保存したり、このようなソース コードで保存したりするべきではないことはわかっています。私は理解を深めようとしているだけで、後でこれをリファクタリングします。

事前にご協力いただきありがとうございます:-D

4

1 に答える 1

0

このany?メソッドは、そのブロックが最初に戻ったときcollectに返すことを除いて、のように動作します。ここでは、配列に対するループのように機能します。truetrue[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. これらの実行のどちらも返されない場合、 が返さtrueany?ます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
于 2012-07-08T00:24:31.197 に答える