【问题标题】:Using OAuth2 with service account on gdata in python在 python 中的 gdata 上使用 OAuth2 和服务帐户
【发布时间】:2013-04-08 05:21:06
【问题描述】:

我想使用data.photos.service.PhotosService 从 Picasa 推送和拉取照片。我从 Google 控制台获得了一个服务密钥文件 XXXXXXXX-privatekey.p12,现在我正在尝试使用该密钥与 google 进行身份验证。

OAUTH2 使用 appengine 的文档让我相信使用以下内容会很有用:

f = file(settings.SITE_ROOT + '/aurora/' + settings.PRIVATE_KEY, 'rb')
key = f.read()
f.close()

credentials = SignedJwtAssertionCredentials(settings.SERVICE_ACCOUNT_NAME, key, scope = 'http://picasaweb.google.com/data https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile')
http = httplib2.Http()
http = credentials.authorize(http)
service = build("oauth2", "v2", http=http)
user_info = None
try:
  user_info = service.userinfo().get().execute()
  # neither of these two methods work
  #gd_client.SetOAuthInputParameters(signature_method = gdata.auth.OAuthSignatureMethod.RSA_SHA1, consumer_key = "asdfasdfasdf.apps.googleusercontent.com", rsa_key = key, two_legged_oauth = True, requestor_id = user_info.get('email'))
  #gd_client.auth_token = gdata.gauth.TwoLeggedOAuthRsaToken(consumer_key = user_info.get('email'), rsa_private_key = key, requestor_id = user_info.get('email'))
except errors.HttpError, e:
  logging.error('An error occurred: %s', e)

user_inf0 = {u'verified_email': True, u'id': u'1234', u'name': u'asdfasdfasdf@developer.gserviceaccount.com', u'email': u'asdfasdfasdf@developer.gserviceaccount.com'}

问题是使用 SetOAuthInputParameters 的方法 1 返回无效令牌,或者方法 2 返回 403 restricted

当我真的并且真的不想那样做时,我正在阅读大量的代码,这些代码都执行常规的 3 legged oauth。我还没有看到任何想法/文章吗?

【问题讨论】:

    标签: google-app-engine oauth-2.0 gdata picasa google-api-client


    【解决方案1】:

    使用 gdata.gauth.OAuth2TokenFromCredentials。

    auth2token = gdata.gauth.OAuth2TokenFromCredentials(credentials)
    gd_client = auth2token.authorize(gd_client)
    

    OAuth2TokenFromCredentials 旨在帮助您同时使用 apiclient 和 gdata。在幕后,它使用凭据来确保它拥有执行 gdata 调用所需的身份验证信息。

    请注意,如果您仍然得到 403,则可能完全是另外一回事。我正在使用服务帐户访问用户的数据并得到 403,因为我没有在 SignedJwtAssertionCredentials 调用中正确指定用户。

    更新:这是我使用的基本模式:

    from oauth2client.client import SignedJwtAssertionCredentials
    credentials = SignedJwtAssertionCredentials(
        "XXXXXXXXXXX@developer.gserviceaccount.com",
        open("keyfile").read(),
        scope=(
            "https://www.googleapis.com/auth/drive",
            "https://spreadsheets.google.com/feeds",
            "https://docs.google.com/feeds"
        ), # For example.
        sub="user@gmail.com"
    )
    http = httplib2.Http()
    http = credentials.authorize(http) # Not needed? See comment below.
    auth2token = gdata.gauth.OAuth2TokenFromCredentials(credentials)
    gd_client = gdata.photos.service.PhotosService() # For example.
    gd_client = auth2token.authorize(gd_client)
    

    【讨论】:

    • 你是如何在SignedJwtAssertionCredentials调用中指定用户的?
    • 我不断收到 HTTP 400,我正在使用电子表格 API
    • Gdata 文档解释桥接 gdata-python-client 和 google-api-python-client github.com/google/gdata-python-client/blob/…
    • @DavidK.Hess 我希望我能再次投票给你的答案以提供模式。
    • SignedJwtAssertionCredentials需要哪个导入?
    【解决方案2】:

    如果您在 Google 帐户上使用 MFA,则需要使用同意屏幕身份验证方法。使用 Picassa API,它不能按原样工作,因为请求 API 略有不同。

    import gdata.gauth
    import os
    import pickle
    import gdata.photos.service
    
    clientid='xxx'  # https://console.developers.google.com/apis/credentials
    clientsecret='xxx'
    Scope='https://picasaweb.google.com/data/'
    User_agent='myself'
    
    def GetAuthToken():
        if os.path.exists(".token"):
            with open(".token") as f:
                token = pickle.load(f)
        else:
            token = gdata.gauth.OAuth2Token(client_id=clientid,client_secret=clientsecret,scope=Scope,user_agent=User_agent)
            print token.generate_authorize_url(redirect_uri='urn:ietf:wg:oauth:2.0:oob')
            code = raw_input('What is the verification code? ').strip()
            token.get_access_token(code)
            with open(".token", 'w') as f:
                pickle.dump(token, f)
        return token
    
    
    token = GetAuthToken()
    
    gd_client = gdata.photos.service.PhotosService()
    old_request = gd_client.request
    
    
    def request(operation, url, data=None, headers=None):
        headers = headers or {}
        headers['Authorization'] = 'Bearer ' + token.access_token
        return old_request(operation, url, data=data, headers=headers)
    
    
    gd_client.request = request
    photos = gd_client.GetUserFeed(kind='photo', limit='10')
    for photo in photos.entry:
        print 'Recently added photo title:', photo.title.text
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-23
      • 2014-01-07
      • 1970-01-01
      • 2015-09-19
      • 2014-09-22
      • 2018-05-09
      • 2014-06-17
      • 1970-01-01
      相关资源
      最近更新 更多