您如何从(非Web)Python客户端访问经过身份validation的Google App Engine服务?
我有一个Google App Engine应用程序 – http://mylovelyapp.appspot.com/它有一个页面 – mylovelypage
目前,页面只是self.response.out.write('OK')
如果我在我的电脑上运行以下Python:
import urllib2 f = urllib2.urlopen("http://mylovelyapp.appspot.com/mylovelypage") s = f.read() print s f.close()
它打印“确定”
问题是如果我添加login:required
在应用程序的yaml这个页面
那么这会打印出Google帐户login页面的HTML
我已经尝试了“正常”的身份validation方法。 例如
passman = urllib2.HTTPPasswordMgrWithDefaultRealm() auth_handler = urllib2.HTTPBasicAuthHandler() auth_handler.add_password(None, uri='http://mylovelyapp.appspot.com/mylovelypage', user='billy.bob@gmail.com', passwd='billybobspasswd') opener = urllib2.build_opener(auth_handler) urllib2.install_opener(opener)
但它没有区别 – 我仍然得到login页面的HTML回来。
我已经尝试了Google的ClientLogin auth API ,但是我无法使它工作。
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" % ("billy.bob@gmail.com", "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
我似乎能够正确地得到一些标记,但是当我打电话给“mylovelypage”时,试图在标题中使用它仍然只是返回login页面的HTML。 🙁
任何人都可以帮忙吗?
我可以使用GData客户端库来做这种事吗? 从我读过的内容来看,我认为它应该可以访问App Engine应用程序,但是我并没有更加成功地使App Engine的authentication工作在那里
任何指向样本,文章,甚至只是关键字的指针,我应该寻找让我开始,将非常感激。
谢谢!
appcfg.py,将数据上传到App Engine的工具必须执行此操作才能使用App Engine服务器进行身份validation。 相关的function被抽象成appengine_rpc.py。 简而言之,解决scheme是:
- 使用Google ClientLogin API获取身份validation令牌。 appengine_rpc.py在_GetAuthToken中执行此操作
- 将身份validation令牌发送到App Engine应用程序上的特殊url。 该页面然后返回一个cookie和一个302redirect。 忽略redirect并存储cookie。 appcfg.py在_GetAuthCookie中执行此操作
- 在以后的所有请求中使用返回的cookie。
您可能还想查看_Authenticate ,看看appcfg如何处理来自ClientLogin和_GetOpener的各种返回代码,以查看appcfg如何创build不遵循HTTPredirect的urllib2 OpenerDirector。 实际上,您可以批量使用AbstractRpcServer和HttpRpcServer类,因为它们几乎可以满足您的所有需求。
感谢Arachnid的答案 – 它按照build议工作
这里是代码的简化副本,以防下一个人试用!
import os import urllib import urllib2 import cookielib users_email_address = "billy.bob@gmail.com" 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
对于无法使用ClientLogin的用户,请尝试应用引擎的OAuth支持 。
我不太熟悉AppEngine或者Google的web apis,但是对于暴力方法,你可以写一个类似mechanize( http://wwwsearch.sourceforge.net/mechanize/ )的脚本来简单地在你之前完成login过程开始做客户的实际工作。
我不是一个Python专家或应用程序引擎专家。 但是,您是否尝试过http://code.google.com/appengine/docs/gettingstarted/usingusers.html中的示例应用程序。; 我在http://quizengine.appspot.com上创build了一个,它似乎在Google身份validation和所有方面都能正常工作。; 只是一个build议,但看看入门指南。 如果这个build议听起来太天真了,那就轻松一点。 :) 谢谢。