52

我有一个 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 帐户登录页面的 HTML

我已经尝试过“正常”的身份验证方法。例如

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)

但这没有什么区别——我仍然得到了登录页面的 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”时尝试在标题中使用它仍然只是返回登录页面的 HTML。:-(

有人可以帮忙吗?

我可以使用GData 客户端库来做这种事情吗?从我读到的内容来看,我认为它应该能够访问 App Engine 应用程序,但我也没有更成功地让 App Engine 的身份验证工作在那里

任何指向样本、文章,甚至只是我应该搜索以帮助我开始的关键字的指针,都将不胜感激。

谢谢!

4

5 回答 5

39

appcfg.py,将数据上传到 App Engine 的工具必须执行此操作才能通过 App Engine 服务器对自身进行身份验证。相关功能被抽象到 appengine_rpc.py 中。简而言之,解决方案是:

  1. 使用Google ClientLogin API获取身份验证令牌。appengine_rpc.py 在_GetAuthToken中执行此操作
  2. 将身份验证令牌发送到 App Engine 应用上的特殊 URL。然后该页面返回一个 cookie 和一个 302 重定向。忽略重定向并存储 cookie。appcfg.py 在_GetAuthCookie中执行此操作
  3. 在以后的所有请求中使用返回的 cookie。

您可能还想查看_Authenticate以了解 appcfg 如何处理来自 ClientLogin 的各种返回码,以及_GetOpener以了解 appcfg 如何创建不遵循 HTTP 重定向的 urllib2 OpenerDirector。或者,实际上,您可以直接使用 AbstractRpcServer 和 HttpRpcServer 类,因为它们几乎可以满足您的所有需求。

于 2008-09-19T14:55:24.780 回答
34

感谢 Arachnid 的回答 - 它按建议工作

这是代码的简化副本,以防对下一个人尝试有所帮助!

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
于 2008-09-19T16:22:06.287 回答
1

对于那些无法让 ClientLogin 工作的人,请尝试应用引擎的OAuth 支持

于 2011-01-27T06:59:18.943 回答
0

我对 AppEngine 或 Google 的 Web api 不太熟悉,但对于蛮力方法,您可以编写一个带有 mechanize ( http://wwwsearch.sourceforge.net/mechanize/ ) 之类的脚本,以便在您之前简单地完成登录过程开始做客户的实际工作。

于 2008-09-19T14:16:24.217 回答
-1

我不是 python 专家或应用程序引擎专家。但是您是否尝试遵循http://code.google.com/appengine/docs/gettingstarted/usingusers.html上的示例应用程序。我在http://quizengine.appspot.com上创建了一个,它似乎与 Google 身份验证和所有内容都可以正常工作。只是一个建议,但请查看入门指南。如果这个建议听起来很幼稚,请放轻松。:) 谢谢。

于 2008-09-19T14:16:12.377 回答