【问题标题】:Using OAuth2 on GAE in python在 Python 中在 GAE 上使用 OAuth2
【发布时间】:2014-09-17 17:52:16
【问题描述】:

我正在尝试创建一个 GAE 应用,用户可以在其中访问 apppot 域,使用 OAuth2 获得授权(或不授权),然后使用 gdata.spreadsheet.service 以自动方式修改他们的 Google 电子表格之一。我已经使用SignedJwtAssertionCredentials 让它工作,但在这种情况下,用户必须明确允许从应用程序进行编辑;我正在尝试跳过此步骤,并让应用使用 OAuth2 从他们自己的帐户修改用户的电子表格。

Google 提供的文档说装饰器是完成此任务的最简单方法,如下所示:

from apiclient.discovery import build
from google.appengine.ext import webapp
from oauth2client.appengine import OAuth2Decorator

decorator = OAuth2Decorator(
  client_id='your_client_id',
  client_secret='your_client_secret',
  scope='https://www.googleapis.com/auth/calendar')

service = build('calendar', 'v3')

...

  @decorator.oauth_required
  def get(self):
    # Get the authorized Http object created by the decorator.
    http = decorator.http()
    # Call the service using the authorized Http object.
    request = service.events().list(calendarId='primary')
    response = request.execute(http=http)

但我不知道如何处理这个service 对象以通过电子表格修改来实现我的目标。有关如何使用 service 对象的任何一般提示或特定提示都会有所帮助。

【问题讨论】:

  • 如果你想尝试的话,我使用simpleauth 进行 gae 的 oauth。

标签: python google-app-engine


【解决方案1】:

在提供的示例中,您正在使用 Google Calendar API(不是基于 GData 的 API)构建日历服务。对于基于 GData 的 API,您必须改用 gdata.gauth

请注意,gdata.spreadsheet.service 不适用于 gdata.gauth,因为它仅支持已弃用的 ClientLogin(请查看 [1] 中的 SpreadsheetsService 构造函数)。你应该改用gdata.spreadsheets.client

完整的 SpreadsheetsClient 文档可在 [2] 获得。您可以考虑这个将工作表添加到电子表格的示例:

import webapp2
import cgi
import atom.data
import gdata.data
import gdata.spreadsheets.client

from oauth2client.client import OAuth2WebServerFlow

SCOPE = 'https://spreadsheets.google.com/feeds'

flow = OAuth2WebServerFlow(
  client_id='your_client_id',
  client_secret='your_client_secret',
  scope=SCOPE,
  redirect_uri='https://your_app.appspot.com/oauth2callback',
  response_type='code')


class OAuthCalback(webapp2.RequestHandler):
    def get(self):
        # Get auth code
        auth_code = cgi.escape(self.request.get('code'))

        # Exchange auth code for credentials
        credentials = flow.step2_exchange(auth_code)

        # Get token from credentials
        auth2token = gdata.gauth.OAuth2Token(client_id=credentials.client_id,
          client_secret=credentials.client_secret,
          scope=SCOPE,
          access_token=credentials.access_token,
          refresh_token=credentials.refresh_token,
          user_agent='AppEngine-Google;(+http://code.google.com/appengine; appid: your_app_id)')

        # Construct client
        spreadsheets_client = gdata.spreadsheets.client.SpreadsheetsClient(source='https://your_app.appspot.com', auth_token=auth2token)

        # Authorize it
        auth2token.authorize(spreadsheets_client)

        # Spreadsheet key
        key = 'your_spreadsheet_key'

        # Add worksheet to the spreadsheet
        entry = spreadsheets_client.add_worksheet(key, 'test', 7, 10)


class MainHandler(webapp2.RequestHandler):
    def get(self):
        # Get url to start authorization
        auth_url = flow.step1_get_authorize_url()

        # Render link
        content = '<a style="display:inline" href="' + auth_url + ' "target="_blank">Authorize</a>'
        self.response.out.write(content)


app = webapp2.WSGIApplication([('/', MainHandler),
                                ('/oauth2callback', OAuthCalback),
                                ], debug=True)

关于 OAuth,我会改用 OAuth2WebServerFlow(请参阅 [3] 了解更多信息)。 Credentials 对象可以使用 pickle 进行序列化和反序列化。 [4] 中描述了更简单的存储凭证对象的方法。

[1] - https://code.google.com/p/gdata-python-client/source/browse/src/gdata/spreadsheet/service.py?r=f7a9cb244df430d960f6187ee0fbf85fe0218aac
[2] - https://gdata-python-client.googlecode.com/hg/pydocs/gdata.spreadsheets.client.html#SpreadsheetsClient
[3] - https://developers.google.com/api-client-library/python/guide/aaa_oauth#OAuth2WebServerFlow
[4] - https://developers.google.com/api-client-library/python/guide/google_app_engine#Credentials

【讨论】:

  • 感谢您的回复。我无法让它工作;我收到一个错误:FlowExchangeError: invalid_request on credentials = flow.step2_exchange(auth_code)
  • 这很奇怪...如果我在同意屏幕上单击“取消”,我可以重现此错误(请参阅postimg.org/image/ot8xdeoj7)。请添加:import loggingerror = cgi.escape(self.request.get('error'))logging.error(error) (just before credentials = flow.step2_exchange(auth_code))。 oauthclient 也会进行日志记录,因此您应该在appengine.google.com 的应用程序日志的日志条目中看到它失败的原因。可以分享一下吗?
  • 当我转到app_name.appspot.com/oauth2callback 时,我得到的错误消息跟踪与您的图像几乎完全相同(除了实现的细节)。当我点击“授权”时,日志中不会产生错误,但我被重定向到一个谷歌页面,上面写着“错误:invalid_client”,下面是“没有应用程序名称”以及一些关于请求的信息
  • 在访问 app_name.appspot.com/oauth2callback 时直接获取 FlowExchangeError: invalid_request 是预期的,因为 /oauth2callback 实现了一个 get 方法处理程序,该处理程序需要在请求中提供授权代码。此处理程序旨在由处理 OAuth 的 Google 服务器调用。至于Error: invalid_client,如果没有设置同意屏幕(例如postimg.org/image/kd8bhftb7),这是预期的。此外,请确保为 Web 应用设置了客户端 ID,并且其重定向 uri 填充了您应用的重定向 api(例如 postimg.org/image/hbxoiqcxr)。
  • 另外,请记住我提供的代码仅供参考。 oauth2callback 处理程序不应执行任何实际操作,而是构造、保存凭据对象并重定向到旨在构造客户端并执行进一步操作的处理程序。
猜你喜欢
  • 2011-11-17
  • 1970-01-01
  • 2013-06-13
  • 2012-09-01
  • 2019-05-02
  • 2013-09-13
  • 1970-01-01
  • 2013-05-31
  • 2016-03-10
相关资源
最近更新 更多