【问题标题】:How to retrieve Google Contacts in Django using oauth2.0?如何使用 oauth2.0 在 Django 中检索 Google 联系人?
【发布时间】:2017-03-02 19:46:28
【问题描述】:

我的应用已在 Google 中注册,并且我已启用联系人 API。

在第一个视图中,我正在获取访问令牌,并将用户重定向到 Google 确认页面,在该页面中将提示他授予其联系人的访问权限:

SCOPE = 'https://www.google.com/m8/feeds/'
CLIENT_ID = 'xxxxxxxx'
CLIENT_SECRET = 'xxxxxxxxx'
APPLICATION= 'example.com'
USER_AGENT = 'dummy-sample'
APPLICATION_REDIRECT_URI = 'http://example.com/oauth2callback/'

def import_contacts(request):

    auth_token = gdata.gauth.OAuth2Token(
        client_id=CLIENT_ID, client_secret=CLIENT_SECRET,
        scope=SCOPE, user_agent=USER_AGENT)

    authorize_url = auth_token.generate_authorize_url(
        redirect_uri=APPLICATION_REDIRECT_URI)

    return redirect(authorize_url)

如果用户点击允许,Google 会重定向到我的处理程序,该处理程序将检索联系人:

def oauth2callback(request):
    code = request.GET.get('code', '')
    redirect_url = 'http://example.com/oauth2callback?code=%s' % code
    url = atom.http_core.ParseUri(redirect_url)

    auth_token.get_access_token(url.query)

    client = gdata.contacts.service.ContactsService(source=APPLICATION)
    auth_token.authorize(client)
    feed = client.GetContactsFeed()

如您所见,我的问题是如何在第二个视图中获取 auth_token 对象,因为此代码在行 auth_token.get_access_token(url.query) 上失败。 我尝试了多个选项,例如将对象放入会话中,但它不是可序列化的,但都没有成功。我也试过gdata.gauth.token_to_blob(auth_token),但我只能检索令牌字符串而不是对象。使用gdata.gauth.ae_save()ae_load() 似乎在某种程度上需要Google App Engine。

我看到的获取联系人的另一种方法是直接在第一个 Django 视图中使用访问令牌请求他们,而不是用代码交换令牌:

r = requests.get('https://www.google.com/m8/feeds/contacts/default/full?access_token=%s&alt=json&max-results=1000&start-index=1' % (self.access_token))

但这并不是将用户重定向到谷歌页面,以便他们可以明确表示同意。相反,它直接使用令牌作为凭据来获取联系人。这是一种常见的做法吗?你怎么看?我认为第一种方法是首选方法,但首先我必须设法获取 auth_token 对象..

【问题讨论】:

  • 我完全不明白你在这里做什么。您自己从字符串构造一个 URL,将其转换为 ParseUri 对象,然后将查询元素传递给get_access_token。为什么?查询元素只是code=<code>,您可以直接构造它。但是,如果您需要更多帮助,则需要链接到您正在使用的确切客户端库,因为 Google 有多个,但您的代码似乎与其中任何一个都不匹配。
  • 但实际上我刚刚意识到你在问什么。我仍然不知道您为什么要这样做,而不是按照 Google 开发人员文档中描述的流程进行操作,但是 OAuth2Token 对象与当前请求没有任何关系 - 它可以很容易地重新实例化回调函数,或者在模块级别实例化一次并在每个函数中使用。
  • 基本上我试图遵循这个例子:stackoverflow.com/questions/10188768/…。我尝试按照这里的官方参考developers.google.com/google-apps/contacts/v3,但我无法构建完整的流程。
  • 这里是我在项目中使用的社交包:django-allauth (0.25.2)django-google-contacts (0.1)gdata (2.0.18)oauthlib (1.1.1)requests-oauthlib (0.6.1)。奇怪的是,但我没有使用教程中提到的gdata-python-client。可能是因为我得到了这个问题吗?
  • 您是否尝试过使用oauth2client library for Python 中指示的 Python oauth 流程?

标签: python django oauth-2.0 gdata google-contacts-api


【解决方案1】:

最后我能够序列化对象并将其放入会话中,这不是一种安全的方法,但至少它会为我指明正确的方向,以便我可以继续与社交相关的业务逻辑应用程序。

import gdata.contacts.client

def import_contacts(request):

    auth_token = gdata.gauth.OAuth2Token(
        client_id=CLIENT_ID, client_secret=CLIENT_SECRET,
        scope=SCOPE, user_agent=USER_AGENT)

    authorize_url = auth_token.generate_authorize_url(
        redirect_uri=APPLICATION_REDIRECT_URI)
    # Put the object in the sesstion
    request.session['auth_token'] = gdata.gauth.token_to_blob(auth_token)

    return redirect(authorize_url)

def oauth2callback(request):
    code = request.GET.get('code', '')
    redirect_url = 'http://myapp.com/oauth2callback?code=%s' % code
    url = atom.http_core.ParseUri(redirect_url)
    # Retrieve the object from the session
    auth_token = gdata.gauth.token_from_blob(request.session['auth_token'])
    # Here is the tricky part: we need to add the redirect_uri to the object in addition
    auth_token.redirect_uri = APPLICATION_REDIRECT_URI

    # And this was my problem in my question above. Now I have the object in the handler view and can use it to retrieve the contacts.
    auth_token.get_access_token(url.query)
    # The second change I did was to create a ContactsClient instead of ContactsService
    client = gdata.contacts.client.ContactsClient(source=APPLICATION)
    auth_token.authorize(client)
    feed = client.GetContacts()

    all_emails = []
    for i, entry in enumerate(feed.entry):
        # Loop and fill the list with emails here
        ...

    return render_to_response('xxx/import_contacts.html', {'all_emails': all_emails},
                          context_instance=RequestContext(request))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多