2008-09-19 12 views
52

Ich habe einen Engine-App Google App - http://mylovelyapp.appspot.com/ Es eine Seite hat - mylovelypageWie greifen Sie über einen (nicht webbasierten) Python-Client auf einen authentifizierten Google App Engine-Dienst zu?

Im Moment funktioniert die Seite nur self.response.out.write('OK')

Wenn ich den folgenden Python an meinem Computer laufen:

import urllib2 
f = urllib2.urlopen("http://mylovelyapp.appspot.com/mylovelypage") 
s = f.read() 
print s 
f.close() 

druckt "OK"

das Problem ist, wenn ich login:required auf dieser Seite in der yaml App hinzufügen

dann druckt das HTML der Login-Seite für Google-Konten

Ich habe "normale" Authentifizierungsmethoden ausprobiert. z.B.

passman = urllib2.HTTPPasswordMgrWithDefaultRealm() 

auth_handler = urllib2.HTTPBasicAuthHandler() 
auth_handler.add_password(None, 
          uri='http://mylovelyapp.appspot.com/mylovelypage', 
          user='[email protected]', 
          passwd='billybobspasswd') 
opener = urllib2.build_opener(auth_handler) 
urllib2.install_opener(opener) 

Aber es macht keinen Unterschied - ich bekomme immer noch das HTML der Anmeldeseite zurück.

Ich habe versucht Google's ClientLogin auth API, aber ich kann es nicht zur Arbeit bekommen.

h = httplib2.Http() 

auth_uri = 'https://www.google.com/accounts/ClientLogin' 
headers = {'Content-Type': 'application/x-www-form-urlencoded'} 
myrequest = "Email=%s&Passwd=%s&service=ah&source=DALELANE-0.0" % ("[email protected]", "billybobspassword") 
response, content = h.request(auth_uri, 'POST', body=myrequest, headers=headers) 

if response['status'] == '200': 
    authtok = re.search('Auth=(\S*)', content).group(1) 

    headers = {} 
    headers['Authorization'] = 'GoogleLogin auth=%s' % authtok.strip() 
    headers['Content-Length'] = '0' 

    response, content = h.request("http://mylovelyapp.appspot.com/mylovelypage", 
            'POST', 
            body="", 
            headers=headers) 

    while response['status'] == "302":   
     response, content = h.request(response['location'], 'POST', body="", headers=headers) 

    print content 

Ich scheine richtig etwas Token in der Lage sein zu bekommen, aber versucht es im Header zu verwenden, wenn ich ‚mylovelypage‘ rufen immer noch zurückkehren mich nur die HTML-Login-Seite. :-(

jemand helfen kann, bitte?

Kann ich die GData client library verwende diese Art der Sache zu tun? Von was ich gelesen habe, denke ich, es sollte in der Lage App Engine-Anwendungen zugreifen zu können, aber ich war nicht mehr erfolgreich bei der Authentifizierung für App Engine Sachen dort entweder

Irgendwelche Hinweise auf Proben, Artikel oder auch nur Keywords Ich sollte suchen, um mich zu starten, wäre sehr viel geschätzt

Vielen Dank!

Antwort

39

appcfg.py, das Tool, das Daten in App Engine hochlädt, muss genau dies tun, um sich mit dem App Engine-Server zu authentifizieren. Die relevante Funktionalität wird in appengine_rpc.py abstrahiert. Kurz gesagt lautet die Lösung:

  1. Verwenden Sie die Google ClientLogin API, um ein Authentifizierungstoken zu erhalten. appengine_rpc.py tut das in _GetAuthToken
  2. Senden Sie das Authentifizierungstoken an eine spezielle URL in Ihrer App Engine App. Diese Seite gibt dann einen Cookie und eine 302-Weiterleitung zurück. Ignoriere die Weiterleitung und speichere den Cookie. appcfg.py tut dies in _GetAuthCookie
  3. Verwenden Sie den zurückgegebenen Cookie in allen zukünftigen Anfragen.

Sie können auch auf _Authenticate sehen, zu sehen, wie appcfg die verschiedenen Rückgabecodes von Clientlogin Griffen und _GetOpener, zu sehen, wie appcfg ein urllib2 OpenerDirector erstellt, die nicht HTTP-Umleitungen folgen. Oder Sie könnten tatsächlich nur die Klassen AbstractRpcServer und HttpRpcServer verwenden, da sie praktisch alles, was Sie brauchen, ausführen.

+1

Ich war soweit, einen Authtoken zu bekommen, aber ich habe es nicht versucht, um einen Keks zu bekommen - vielen Dank für den Zeiger! – dalelane

+0

Ich habe die Quelle in einer neuen "Antwort" unten - danke wieder – dalelane

+0

Links sind gebrochen ("_GetAuthToken", "_GetAuhtcookie", etc.) – dfrankow

-1

Ich bin kein Python-Experte oder App-Engine-Experte. Aber haben Sie versucht, die Beispielanwendung unter http://code.google.com/appengine/docs/gettingstarted/usingusers.html zu folgen. Ich habe einen unter http://quizengine.appspot.com erstellt, es schien gut mit Google-Authentifizierung und allem zu funktionieren. Nur ein Vorschlag, aber schauen Sie in den Leitfaden für die ersten Schritte. Nimm es leicht, wenn der Vorschlag naiv klingt. :) Danke.

+2

Danke für den Kommentar. Das Problem tritt jedoch nicht in einer App Engine-App auf. Wie Sie sagen - das ist einfach. Das Problem ist der Zugriff auf die App-Engine von einem Python-Code auf meinem Desktop-Computer ausgeführt. Von hier aus betrete ich das authentifizierte Google-Ökosystem. – dalelane

0

Ich bin nicht zu vertraut mit AppEngine oder Googles Web Apis, aber für eine Brute - Force - Ansatz könnten Sie ein Skript mit etwas wie mechanize (http://wwwsearch.sourceforge.net/mechanize/) einfach durch den Login - Prozess zu gehen, bevor Sie beginnen, die eigentliche Arbeit der Klient.

34

Dank für die Antwort auf Arachnid - es wie vorgeschlagen

arbeitete hier

eine vereinfachte Kopie des Codes ist, falls es an die nächste Person hilfreich zu versuchen!

import os 
import urllib 
import urllib2 
import cookielib 

users_email_address = "[email protected]" 
users_password  = "billybobspassword" 

target_authenticated_google_app_engine_uri = 'http://mylovelyapp.appspot.com/mylovelypage' 
my_app_name = "yay-1.0" 



# we use a cookie to authenticate with Google App Engine 
# by registering a cookie handler here, this will automatically store the 
# cookie returned when we use urllib2 to open http://currentcost.appspot.com/_ah/login 
cookiejar = cookielib.LWPCookieJar() 
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar)) 
urllib2.install_opener(opener) 

# 
# get an AuthToken from Google accounts 
# 
auth_uri = 'https://www.google.com/accounts/ClientLogin' 
authreq_data = urllib.urlencode({ "Email": users_email_address, 
            "Passwd": users_password, 
            "service": "ah", 
            "source": my_app_name, 
            "accountType": "HOSTED_OR_GOOGLE" }) 
auth_req = urllib2.Request(auth_uri, data=authreq_data) 
auth_resp = urllib2.urlopen(auth_req) 
auth_resp_body = auth_resp.read() 
# auth response includes several fields - we're interested in 
# the bit after Auth= 
auth_resp_dict = dict(x.split("=") 
         for x in auth_resp_body.split("\n") if x) 
authtoken = auth_resp_dict["Auth"] 

# 
# get a cookie 
# 
# the call to request a cookie will also automatically redirect us to the page 
# that we want to go to 
# the cookie jar will automatically provide the cookie when we reach the 
# redirected location 

# this is where I actually want to go to 
serv_uri = target_authenticated_google_app_engine_uri 

serv_args = {} 
serv_args['continue'] = serv_uri 
serv_args['auth']  = authtoken 

full_serv_uri = "http://mylovelyapp.appspot.com/_ah/login?%s" % (urllib.urlencode(serv_args)) 

serv_req = urllib2.Request(full_serv_uri) 
serv_resp = urllib2.urlopen(serv_req) 
serv_resp_body = serv_resp.read() 

# serv_resp_body should contain the contents of the 
# target_authenticated_google_app_engine_uri page - as we will have been 
# redirected to that page automatically 
# 
# to prove this, I'm just gonna print it out 
print serv_resp_body 
+0

Wie sieht es in der Entwicklungsumgebung aus? – dfrankow

+0

Das heißt, wenn Sie sich lokal authentifizieren möchten statt über https://www.google.com/accounts – dfrankow

+0

Um sich lokal zu authentifizieren, geben Sie einfach ein einfaches Cookie mit dem gewünschten Benutzernamen ein. Sniff eine Anfrage, um genau zu sehen, was es ist. :) –

1

für diejenigen, die nicht zu arbeiten Clientlogin bekommen, versuchen OAuth support App Engine.