0

我有我自己有點卡住試圖讓HTTP摘要式身份驗證和運行,很像在導向建議的快速位:使用明文密碼與authenticate_or_request_with_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

一個巨大的感謝你的幫助的any?方法就像collect,除了它返回true第一次了塊11返回true。在這裏,它的作用就像一個循環陣列[true, false]過來:

  1. 該塊是與password_is_ha1集到true第一次運行。如果該塊返回true,any?立即返回true,並且由於這是validate_digest_response的最後一條語句,該方法作爲整體返回true

  2. 否則,塊再次運行,password_is_ha1設置爲false。如果該塊返回true,any?立即返回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