1

我正在开发一个小网络应用程序来帮助我管理我的 gmail。我已经通过 Google 的 API 使用我通过django-allauth.

import google.oauth2.credentials
from .choices import GMAIL
from allauth.socialaccount.models import SocialToken, SocialAccount
from apiclient.discovery import build


def get_credentials(user):
    account = SocialAccount.objects.get(user=user.id)
    token = SocialToken.objects.get(app=GMAIL, account=account).token
    credentials = google.oauth2.credentials.Credentials(token)
    service = build('gmail', 'v1', credentials=credentials)
    return service

这有时似乎有效,但不幸的是,它不是很可靠。它在build()函数中经常超时,只有大约三分之一的时间成功。我想知道是什么导致了这种行为,是否有更可靠的方式来访问 API?

我从这些文档中找到了以下AuthorizedSession类:

from google.auth.transport.requests import AuthorizedSession

authed_session = AuthorizedSession(credentials)

response = authed_session.request(
    'GET', 'https://www.googleapis.com/storage/v1/b')

但我不知道如何将其变成与 Google API 一起使用的对象:

def get_labels(user):
    service = get_credentials(user)
    results = service.users().labels().list(userId='me').execute()
    labels = results.get('labels', [])
    return labels

不幸的是,Google 的文档建议使用我希望避免的已弃用包。

这是我第一次真正使用 OAuth 强制 API。有人有建议吗?

编辑:我从我的 Macbook 尝试后发布。我也在我的 Windows 机器上尝试过它,它的工作更一致,但每次只需要大约 20 秒才能完成build(). 我觉得我做错了什么。

4

1 回答 1

0

在我最终将刷新令牌添加到组合中之后,今天早上这工作得更好。也许它的缺席在另一端引起了一些问题。我将继续测试,但现在一切正常:

这是我的完整解决方案:

import google.oauth2.credentials
from google.auth.transport.requests import Request

from apiclient import errors, discovery

from myproject.settings import GMAIL_CLIENT_API_KEY, GMAIL_CLIENT_API_SECRET


def get_credentials(user):
    token_set = user.socialaccount_set.first().socialtoken_set.first()
    token = token_set.token
    refresh_token = token_set.token_secret
    credentials = google.oauth2.credentials.Credentials(
        token,
        refresh_token=refresh_token,
        client_id=GMAIL_CLIENT_API_KEY,
        client_secret=GMAIL_CLIENT_API_SECRET,
        token_uri= google.oauth2.credentials._GOOGLE_OAUTH2_TOKEN_ENDPOINT,
    )

    if credentials.expired:
        request = Request()
        credentials.refresh(request)

    service = discovery.build('gmail', 'v1', credentials=credentials)
    return service

如您所见,我将 API 密钥添加到我的设置文件中并在此处引用它们。昨天我碰巧偶然发现token_uri了源文件。refresh_token是花了最长时间找到的一块。

好消息是 django-allauth 会将刷新令牌保存到列SocialToken下的模型中token_secret。但是,只有在您的设置中有以下内容时,它才会这样做:

SOCIALACCOUNT_PROVIDERS = {
    'google': {
        'SCOPE': [
            'profile',
            'email',
            'https://www.googleapis.com/auth/gmail.labels',
            'https://www.googleapis.com/auth/gmail.modify'
        ],
        'AUTH_PARAMS': {
            'access_type': 'offline',
        }
    }
}

具体来说,必须根据 docsaccess_type将in设置为。AUTH_PARAMS'offline'

现在,如果您在实施此更改之前连接了您的帐户,这仍然会给您带来麻烦,因此您还需要通过您的Google 权限撤销对您的应用程序的访问权限以获取新的刷新令牌。更多相关信息可以在这个问题中找到。

我不确定这是否是正确/有意的做法,但在谷歌更新他们的 Django 文档之前,这种方法至少应该适用于测试目的。

于 2018-10-27T15:14:12.360 回答