我正在使用Python中的Google Contacts API和Google Calendar API。前者是GData API,后者是Google API ... API,因此当客户端可用时,他们每个都由不同的客户端覆盖 - 这里GData和{{ 3}}
我遇到与这些客户合作的问题是他们都有自己的处理OAuth2的方式。 GData库提供gdata.gauth.token_to_blob(auth_token)
和gdata.gauth.token_from_blob(auth_token)
方法将auth令牌转换为字符串以存储在数据库中,而google-api库提供Google API(平台I' m写作)以存储OAuth凭证。
我没有看到一个明确的方法来存储两个API都可以访问的单个内容(无论是访问令牌还是凭据),但我真的不想要用户必须进行两次身份验证。有没有办法实现这一点,除非放弃谷歌的客户端库并编写直接的HTTP调用?
答案 0 :(得分:3)
我能够得到以下工作。它使用oauth2decorator
来完成繁重的工作,然后使用小帮助程序类TokenFromOAuth2Creds
将相同的凭据应用于gdata客户端。
我应该预先假定我不是gdata专家 - 并且可能有更好的方法来做到这一点 - 我还没有彻底测试过。
import webapp2
import httplib2
from oauth2client.appengine import oauth2decorator_from_clientsecrets
from apiclient.discovery import build
import gdata.contacts.client
decorator = oauth2decorator_from_clientsecrets(
"client_secrets.json",
scope=["https://www.google.com/m8/feeds", "https://www.googleapis.com/auth/calendar.readonly"]
)
# Helper class to add headers to gdata
class TokenFromOAuth2Creds:
def __init__(self, creds):
self.creds = creds
def modify_request(self, req):
if self.creds.access_token_expired or not self.creds.access_token:
self.creds.refresh(httplib2.Http())
self.creds.apply(req.headers)
class MainHandler(webapp2.RequestHandler):
@decorator.oauth_required
def get(self):
# This object is all we need for google-api-python-client access
http = decorator.http()
# Create a gdata client
gd_client = gdata.contacts.client.ContactsClient(source='<var>YOUR_APPLICATION_NAME</var>')
# And tell it to use the same credentials
gd_client.auth_token = TokenFromOAuth2Creds(decorator.get_credentials())
# Use Contacts API with gdata library
feed = gd_client.GetContacts()
for i, entry in enumerate(feed.entry):
self.response.write('\n%s %s' % (i+1, entry.name.full_name.text if entry.name else ''))
# Use Calendar API with google-api-python-client
service = build("calendar", "v3")
result = service.calendarList().list().execute(http=http)
self.response.write(repr(result))
app = webapp2.WSGIApplication([
("/", MainHandler),
(decorator.callback_path, decorator.callback_handler()),
], debug=True)
注意,如果您没有使用装饰器,并且通过其他方式获得了您的凭证对象,则可以通过以下方式创建相同的预授权http对象:
http = credentials.authorize(httplib2.Http())
使用gdata的另一种方法是直接使用http
对象(由decorator.http()
返回) - 此对象将自动为您添加正确的授权标头 - 这可用于向API,但您需要处理制作请求并自行解析XML / JSON:
class MainHandler(webapp2.RequestHandler):
@decorator.oauth_required
def get(self):
http = decorator.http()
self.response.write(http.request('https://www.google.com/m8/feeds/contacts/default/full')[1])
self.response.write(http.request('https://www.googleapis.com/calendar/v3/users/me/calendarList')[1])
httplib2的文档: http://httplib2.googlecode.com/hg/doc/html/libhttplib2.html#http-objects
答案 1 :(得分:0)
您似乎需要破解自己的方式并重写GData API,以便您使用Storage中的令牌。
但是,即使您能够使GData按照您的意愿运行,请记住,为某些范围提供了令牌,因此您需要强制GData API使用Google Calendar API,反之亦然。但我不知道是否可以这样做。