2008-09-19 17 views
52

Tengo una aplicación de Google App Engine - http://mylovelyapp.appspot.com/ Tiene una página - mylovelypage¿Cómo accedes a un servicio autenticado de Google App Engine desde un cliente python (no web)?

Por el momento, la página sólo hace self.response.out.write('OK')

Si funciono el siguiente Python en mi computadora:

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

imprime "OK"

el problema es si añado login:required a esta página en yaml de la aplicación

luego imprime el código HTML de la página de inicio de sesión de Cuentas de Google

He intentado con enfoques de autenticación "normales". p.ej.

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) 

Pero no hace la diferencia - Aún consigo el HTML de la página de inicio de sesión.

He intentado Google's ClientLogin auth API, pero no puedo hacerlo funcionar.

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 

que parecen ser capaces de obtener alguna muestra correctamente, pero los intentos de utilizarlo en la cabecera cuando llamo 'mylovelypage' todavía me acaba de regresar HTML de la página de inicio de sesión. :-(

puede ayudar a nadie, por favor?

podría utilizar el GData client library hacer este tipo de cosas? De lo que he leído, creo que debería ser capaz de acceder a las aplicaciones de App Engine, pero no he tenido más éxito en conseguir que la autenticación funcione para App Engine. O bien

Cualquier puntero a muestras, artículos o incluso solo palabras clave debería ser en la búsqueda para comenzar, sería mucho apreciado.

¡Gracias!

Respuesta

39

appcfg.py, la herramienta que carga datos en App Engine tiene que hacer exactamente esto para autenticarse con el servidor de App Engine. La funcionalidad relevante se resume en appengine_rpc.py. En pocas palabras, la solución es:

  1. Utilice Google ClientLogin API para obtener un token de autenticación. appengine_rpc.py hace esto en _GetAuthToken
  2. Envía el token de autenticación a una URL especial en tu aplicación de App Engine. Esa página luego devuelve una cookie y un redireccionamiento 302. Ignore la redirección y almacene la cookie. appcfg.py hace esto en _GetAuthCookie
  3. Use la cookie devuelta en todas las solicitudes futuras.

También es posible que desee ver en _Authenticate, para ver cómo maneja appcfg los distintos códigos de retorno de ClientLogin, y _GetOpener, para ver cómo appcfg crea una OpenerDirector urllib2 que no sigue las redirecciones HTTP. O podría, de hecho, simplemente usar las clases AbstractRpcServer y HttpRpcServer al por mayor, ya que hacen prácticamente todo lo que necesita.

+1

Llegué a obtener un authtoken, pero no había intentado usarlo para obtener una cookie, ¡muchas gracias por el puntero! – dalelane

+0

He incluido la fuente en una nueva 'respuesta' a continuación - gracias de nuevo – dalelane

+0

Los enlaces están rotos ("_GetAuthToken", "_GetAuhtcookie", etc.) – dfrankow

-1

No soy un experto en python o un experto en motores de aplicaciones. Pero, ¿trataste de seguir el ejemplo de aplicación al http://code.google.com/appengine/docs/gettingstarted/usingusers.html. Creé uno en http://quizengine.appspot.com, parecía funcionar bien con la autenticación de Google y todo. Solo una sugerencia, pero consulte la guía de introducción. Tómatelo con calma si la sugerencia parece ingenua. :) Gracias.

+2

Gracias por el comentario. Sin embargo, el problema no es la autenticación en una aplicación de App Engine. Como dices, eso es sencillo. El problema es acceder al motor de la aplicación desde un código Python que se ejecuta en mi computadora de escritorio. Entrar en el ecosistema de Google autenticado desde aquí es a lo que me ato. – dalelane

0

No estoy demasiado familiarizado con AppEngine, o Googles web apis, pero para un enfoque de fuerza bruta podrías escribir un script con algo como mechanize (http://wwwsearch.sourceforge.net/mechanize/) para simplemente recorrer el proceso de inicio de sesión antes de comenzar a hacer el trabajo real cliente.

34

gracias a Arácnido para la respuesta - funcionó como se sugiere

aquí es una copia simplificada del código, en caso de que sea útil a la siguiente persona para probar!

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

¿Qué tal en el entorno de desarrollo? – dfrankow

+0

Es decir, cuando desea autenticarse localmente en lugar de https://www.google.com/accounts – dfrankow

+0

Para autenticarse localmente, solo debe proporcionar una cookie simple con el nombre de usuario deseado. Escuche una solicitud para ver exactamente qué es. :) –

1

para aquellos que no pueden conseguir ClientLogin para trabajar, intente aplicación del motor de OAuth support.

Cuestiones relacionadas