如何在不需要人为干预的情况下,使用Google Drive SDK 2和Python获取OAuth凭据

4
我有一个Python应用程序,从第三方源获取数据,选择子集,并将其写入CSV文件,然后上传到Google Drive并转换为电子表格。我想将其作为cron任务运行,但目前SDK需要人类与浏览器进行交互以获取OAuth凭据。
我已经搜索了Drive SDK文档,但没有找到任何帮助。我还尝试使用机械化库自动化OAuth过程,但未成功。我相信我错过了什么。我无法相信Drive API需要人类交互。有什么建议吗?
我参考了https://developers.google.com/accounts/docs/OAuth2WebServer#overview,并尝试了以下方法。
flow = OAuth2WebServerFlow(settings.CLIENT_ID, settings.CLIENT_SECRET
                           setings.OAUTH_SCOPE,settings.REDIRECT_URI)
authorize_url = flow.step1_get_authorize_url()

创建请求URL:
https://accounts.google.com/o/oauth2/auth?
scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive&
redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&
response_type=code&
client_id=999637210521.apps.googleusercontent.com&
access_type=offline

使用requests库,我发出以下请求:
r = req.get(authorize_url)
但响应正文是一个没有代码的HTML文档。
3个回答

1

我之前也遇到了同样的问题。

解决方案:保存凭据以供将来使用。请参考以下网址:

https://developers.google.com/accounts/docs/OAuth2#installed

https://developers.google.com/accounts/docs/OAuth2InstalledApp

from oauth2client.file import Storage
...
storage = Storage('a_credentials_file')
storage.put(credentials)
...
credentials = storage.get()

我将我的脚本推送到Github,其中我正在重复使用凭据以创建新的令牌。

https://github.com/sukujgrg/google_drive


第一次和凭证过期时,您仍然需要交互式获取凭证,对吗?从API文档中的示例来看,您应该能够获得包含代码的响应,就像我上面的初始示例中引用的那样。 - Robert
是的,第一次我们需要人类互动。只要用户没有撤销授予应用程序的访问权限,我们就不需要人类互动。https://developers.google.com/accounts/docs/OAuth2InstalledApp#refresh - Suku

0

免责声明:

我不是安全专家,也不知道我的可怕解决方案涉及哪些风险...但它将使您的代码能够在Cron上运行。

如果您愿意为您的应用程序进行一次手动访问接受,并给出一些范围,例如Google快速入门示例(有用的部分发布在答案底部):https://developers.google.com/drive/web/quickstart/python

然后,您可以将CLIENT_SECRET_FILEdrive-quickstart.json文件添加到您的存储库中,这两个文件只需生成一次。然后,如果您有某个Google Drive帐户,您始终希望任何副本都可以访问它,那么就永远不会再次检查凭据。

再次免责声明:

直观地说,这种解决方案对于安全性来说是可怕的,一旦您的代码库以任何方式公开,那么您的Google Drive就完全面临被破坏、删除、禁止等风险...

import httplib2
import os

from apiclient import discovery
import oauth2client
from oauth2client import client
from oauth2client import tools

def get_credentials():

    try:
        import argparse
        flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
    except ImportError:
        flags = None

    SCOPES = 'https://www.googleapis.com/auth/drive'
    #ASSUME THAT THE CLIENT SECRETE FILE BELOW IS STORED IN YOUR CODE BASE
    CLIENT_SECRET_FILE = 'client_secret.json'
    APPLICATION_NAME = 'Drive API Quickstart'

    #ASSUME THAT THIS FILE BELOW IS STORED INSIDE YOUR CODE BASE
    credential_dir = os.path.realpath('')
    credential_path = os.path.join(credential_dir,
                                   'drive-quickstart.json')

    store = oauth2client.file.Storage(credential_path)
    credentials = store.get()
    if not credentials or credentials.invalid:
        flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
        flow.user_agent = APPLICATION_NAME
        if flags:
            credentials = tools.run_flow(flow, store, flags)
        else: # Needed only for compatability with Python 2.6
            credentials = tools.run(flow, store)
        print('Storing credentials to ' + credential_path)
    return credentials

def oneTimeRunCredentials():
    credentials = get_credentials()
    http = credentials.authorize(httplib2.Http())
    service = discovery.build('drive', 'v2', http=http)
    results = service.files().list(maxResults=10).execute()

一旦您运行了此脚本,并将所有三个文件添加到您的代码库中-> 您的cron以及其他任何拥有此代码库的机器上的cron-> 应该可以正常运行。 - D A

0

我看到了这个内容,它有像这样的例子:<p>code = self.request.get(&#39;code&#39;)</p> 但请求的结构是什么? - Robert
1
好的,我明白了。那么你是否已经进入 API 访问面板,并使用“服务器密钥”设置了该项目?默认密钥是“浏览器密钥”,旨在供键盘上的人使用...虽然仍可以使用 Python 请求模块伪造。但是,如果您要在 Cron 上设置它,则应使用“服务器密钥”来完成。 - christoph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接