开发者

Get password inside authenticate_or_request_with_http_digest

I have an app which connects to an iphone app, which in turn authenticates it's users via http_digest.

I'm using authlogic, and in my schema users of the website are "users" and users of the phone app are "people". So, i have user_sessions and people_sessions. To handle the http_digest auth, i'm using the authenticate_or_request_with_http_digest method like this:

def digest_authenticate_person
  authenticate_or_request_with_http_digest do |email, password|
    #ldb is just a logging method i have
    ldb "email = #{email.inspect}, password = #{password.inspect}"
    person = Person.find_by_email(email)
    if person
      ldb "Authentication successful: Got person with id #{person.id}"
      @current_person_session = PersonSession.create(person)        
    else
      ldb "Authentication failed"
      @current_person_session = nil
    end
    return @current_person_session
  end
end

I can see in the logs that password is nil: only email is passed through to the inside of the authenticate_or_request_with_http_digest block.

Im testing this with a curl call like so:

curl --digest --user fakename@madeup.xyz:apass "http://localhost:3000/reports.xml"

I'd expect "fakename@madeup.xyz" and "apass" to get passed through to the inside of the block. Once i have the password then i can use a combination of email and password to find (or not) a user, in the normal way. Does anyone know how i can get acc开发者_如何学Pythoness to the password as well?

grateful for any advice - max

EDIT - on further googling, i think i'm using this method wrong: i'm supposed to just return the password, or the crypted password. But then how do i compare that against the password passed as part of the http_digest username?


Found the answer: i had a fundamental misunderstanding of how authenticate_or_request_with_http_digest works: after reading the documentation (in the source code of the gem) i realised that the purpose of this method is not to do the authentication, its purpose is to provide the "email:realm:password" string to the browser, let the browser encrypt it, and check the result against it's own calculated (or cached) version of this.

Here's how i set it up:

def current_person
  if @current_person
    @current_person
  else
    load_current_person
  end
end 

#use in before_filter for methods that require an authenticated person (mobile app user)
def require_person
  unless current_person
    redirect_to root_path
  end   
end

def load_current_person
  #check user agent to see if we're getting the request from the mobile app
  if request.env['HTTP_USER_AGENT'] =~ /MobileAppName/
    result = digest_authenticate_person
    if result == 401
      return 401
    elsif result == true
      #make authlogic session for person
      @current_person_session = PersonSession.new(@person_from_digest_auth)
      @current_person = @person_from_digest_auth
    end
  end
end  

#this method returns either true or 401
def digest_authenticate_person
  authenticate_or_request_with_http_digest(Person::DIGEST_REALM) do |email|
    person = Person.find_by_email(email)
    @result = nil
    if person
      #need to send back ha1_password for digest_auth, but also hang on to the person in case we *do* auth them successfully
      @person_from_digest_auth = person
      @result = person.ha1_password  
    else
      @person_from_digest_auth = nil
      @result = false
    end
    @result
  end
end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜