自动化pydrive验证过程

alv*_*vas 49 python cloud google-api google-drive-api pydrive

我正在尝试GoogleAuth使用该pydrive库(https://pypi.python.org/pypi/PyDrive)自动化该过程.

我已经设置了pydrive和google API,以便我的secret_client.json工作,但每次运行我的脚本时都需要对gdrive访问进行Web身份验证:

from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive

gauth = GoogleAuth()
gauth.LocalWebserverAuth()

drive = GoogleDrive(gauth)

textfile = drive.CreateFile()
textfile.SetContentFile('eng.txt')
textfile.Upload()
print textfile

drive.CreateFile({'id':textfile['id']}).GetContentFile('eng-dl.txt')
Run Code Online (Sandbox Code Playgroud)

eng.txt只是一个文本文件.此外,当我登录到另一个帐户时,我尝试使用上面的脚本.它不会上传eng.txt到生成我的gdrive secret_client.json但是我授权身份验证时登录的帐户

从上一篇文章中,我尝试了以下内容来自动执行验证过程,但它给出了错误消息:

import base64, httplib2
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive

from apiclient.discovery import build
from oauth2client.client import SignedJwtAssertionCredentials
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive

#gauth = GoogleAuth()
#gauth.LocalWebserverAuth()

# from google API console - convert private key to base64 or load from file
id = "464269119984-j3oh4aj7pd80mjae2sghnua3thaigugu.apps.googleusercontent.com"
key = base64.b64decode('COaV9QUlO1OdqtjMiUS6xEI8')

credentials = SignedJwtAssertionCredentials(id, key, scope='https://www.googleapis.com/auth/drive')
credentials.authorize(httplib2.Http())

gauth = GoogleAuth()
gauth.credentials = credentials

drive = GoogleDrive(gauth)

drive = GoogleDrive(gauth)

textfile = drive.CreateFile()
textfile.SetContentFile('eng.txt')
textfile.Upload()
print textfile

drive.CreateFile({'id':textfile['id']}).GetContentFile('eng-dl.txt')
Run Code Online (Sandbox Code Playgroud)

错误:

Traceback (most recent call last):
  File "/home/alvas/git/SeedLing/cloudwiki.py", line 29, in <module>
    textfile.Upload()
  File "/usr/local/lib/python2.7/dist-packages/pydrive/files.py", line 216, in Upload
    self._FilesInsert(param=param)
  File "/usr/local/lib/python2.7/dist-packages/pydrive/auth.py", line 53, in _decorated
    self.auth.Authorize()
  File "/usr/local/lib/python2.7/dist-packages/pydrive/auth.py", line 422, in Authorize
    self.service = build('drive', 'v2', http=self.http)
  File "/usr/local/lib/python2.7/dist-packages/oauth2client/util.py", line 132, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/apiclient/discovery.py", line 192, in build
    resp, content = http.request(requested_url)
  File "/usr/local/lib/python2.7/dist-packages/oauth2client/util.py", line 132, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/oauth2client/client.py", line 475, in new_request
    self._refresh(request_orig)
  File "/usr/local/lib/python2.7/dist-packages/oauth2client/client.py", line 653, in _refresh
    self._do_refresh_request(http_request)
  File "/usr/local/lib/python2.7/dist-packages/oauth2client/client.py", line 677, in _do_refresh_request
    body = self._generate_refresh_request_body()
  File "/usr/local/lib/python2.7/dist-packages/oauth2client/client.py", line 861, in _generate_refresh_request_body
    assertion = self._generate_assertion()
  File "/usr/local/lib/python2.7/dist-packages/oauth2client/client.py", line 977, in _generate_assertion
    private_key, self.private_key_password), payload)
  File "/usr/local/lib/python2.7/dist-packages/oauth2client/crypt.py", line 131, in from_string
    pkey = crypto.load_pkcs12(key, password).get_privatekey()
OpenSSL.crypto.Error: [('asn1 encoding routines', 'ASN1_get_object', 'header too long')]
Run Code Online (Sandbox Code Playgroud)

我在gdrive api上的身份验证如下所示:

在此输入图像描述

我怎么能使用pydrive这样我每次使用它时都不需要进行身份验证?

如何允许自动身份验证,以便使用pydrive脚本的python脚本只会上传到生成secret_client.jsonInternet浏览器而不是当前登录帐户的帐户?

dan*_*ano 87

首先,你误解了一个非常重要的一点:

当我在登录其他帐户时尝试使用上述脚本时.它不会将eng.txt上传到生成secret_client.json的gdrive中,而是在我授权身份验证时登录的帐户

这正是它应该如何工作的.作为开发人员,client_secret.json您随应用程序一起分发,PyDrive使用该文件通过Google 对应用程序进行身份验证.谷歌想要知道每个应用程序有多少API请求出于各种原因(指标,收费帐户,撤销访问等),因此它需要应用程序进行身份验证.

现在,当您的应用程序运行时LocalWebserverAuth,它正在使用Google 对客户端进行身份验证.当然,客户是实际使用您的应用程序的人.在这种情况下,开发人员和客户是同一个人(您),但想象您希望将您的应用程序分发给数百万不同的人.他们需要能够对自己进行身份验证并将文件上传到他们自己的云端硬盘帐户,而不是让他们全部都在您的(开发人员)中提供client_secret.json.

也就是说,它实际上只是一个非常小的变化,因此您的应用程序无需每次运行应用程序时都要求客户端进行身份验证.你只需要使用LoadCredentialsFileSaveCredentialsFile.

from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive

gauth = GoogleAuth()
# Try to load saved client credentials
gauth.LoadCredentialsFile("mycreds.txt")
if gauth.credentials is None:
    # Authenticate if they're not there
    gauth.LocalWebserverAuth()
elif gauth.access_token_expired:
    # Refresh them if expired
    gauth.Refresh()
else:
    # Initialize the saved creds
    gauth.Authorize()
# Save the current credentials to a file
gauth.SaveCredentialsFile("mycreds.txt")

drive = GoogleDrive(gauth)

textfile = drive.CreateFile()
textfile.SetContentFile('eng.txt')
textfile.Upload()
print textfile

drive.CreateFile({'id':textfile['id']}).GetContentFile('eng-dl.txt')
Run Code Online (Sandbox Code Playgroud)

  • 这让我很快乐.谢谢 :) (6认同)
  • @Gregg您仍需要`client_secrets.json`来验证App.`mycreds.txt`将存储可用于验证用户身份的令牌.因此,第一次运行此代码时,您需要通过Web浏览器输入验证码.第二次,它应该使用`mycreds.txt`中保存的凭据. (4认同)
  • 应该将此代码添加到PyDrive的主页!! (4认同)
  • 这个方法与@ wang892的方法相比如何?在令牌过期后我是否需要手动授权? (3认同)
  • 就像@Joe,您成就了我的一天。我很感激 (2认同)
  • @dano你真棒 (2认同)
  • @sh37211 这只是提问者试图上传的文件。它与身份验证过程无关。 (2认同)

小智 11

整个线程对我帮助很大,但是在我实施了此处介绍的所有解决方案后,又出现了一个问题:LocalWebserverAuth() 将不会获得刷新令牌

如果您打开实现@dano 代码后生成的“mycreds.txt”,您会看到“刷新令牌”将设置为“空”。几个小时后,令牌过期,您将获得以下信息,最终不得不再次手动进行身份验证。

错误:

raise RefreshError('No refresh_token found.') pydrive.auth.RefreshError: No refresh_token found.Please set access_type of OAuth to offline.
Run Code Online (Sandbox Code Playgroud)

解决方案是在 GoogleAuth 的流参数上强制批准_​​promt 并将 access_type 设置为离线。

这是我没有更多错误的方法:

gauth = GoogleAuth()

# Try to load saved client credentials
gauth.LoadCredentialsFile("mycreds.txt")

if gauth.credentials is None:
    # Authenticate if they're not there

    # This is what solved the issues:
    gauth.GetFlow()
    gauth.flow.params.update({'access_type': 'offline'})
    gauth.flow.params.update({'approval_prompt': 'force'})

    gauth.LocalWebserverAuth()

elif gauth.access_token_expired:

    # Refresh them if expired

    gauth.Refresh()
else:

    # Initialize the saved creds

    gauth.Authorize()

# Save the current credentials to a file
gauth.SaveCredentialsFile("mycreds.txt")  

drive = GoogleDrive(gauth)
Run Code Online (Sandbox Code Playgroud)

谢谢你们!


小智 10

另一种方法是通过将setting.yaml文件写入工作目录来使用自定义身份验证流程.此方法效果更好,因为LocalWebserverAuth()生成的令牌只需一小时即可到期,并且没有刷新令牌.

示例settings.yaml文件如下所示

client_config_backend: file
client_config:
    client_id: <your_client_id>
    client_secret: <your_secret>

save_credentials: True
save_credentials_backend: file
save_credentials_file: credentials.json

get_refresh_token: True

oauth_scope:
    - https://www.googleapis.com/auth/drive
    - https://www.googleapis.com/auth/drive.install
Run Code Online (Sandbox Code Playgroud)

使用此文件,您仍然必须使用浏览器首次完成身份验证,之后将使用刷新令牌在工作目录中生成credentials.json文件.

如果您尝试在服务器上自动化脚本,则此方法可以更好地工作

  • 你能提供一些类似于上面提供的dano示例的代码,它显示了你的身份验证代码是如何工作的吗? (3认同)
  • 谢谢,这就像一个魅力!PyDrive 快速入门指南对细节不太清楚。 (2认同)

abu*_*abu 5

这只是为了完成上面@wang892 的帖子(我没有足够的声誉来发表评论)。

这个答案帮助我自动化了我的脚本(不必每次运行它时都重新进行身份验证)。

但当我使用PyDrive 文档中提供的示例 settings.yaml 文件时,我遇到了问题(由于我完全不了解 oauth 的工作原理)。

该示例文件包含这些行,我认为这些行限制了我的 PyDrive 脚本只能访问其自身创建的文件和文件夹(有关详细信息,请参阅PyDrive 问题 #122):

访问受限:

oauth_scope:
  - https://www.googleapis.com/auth/drive.file
  - https://www.googleapis.com/auth/drive.install
Run Code Online (Sandbox Code Playgroud)

当我更改这些行时,问题就解决了(我必须删除存储的凭据并运行脚本来重新授权它,只是再次)。

通过这些新行,我的脚本现在可以访问我的 Google 云端硬盘中的所有文件:

完全访问权限:

oauth_scope:
  - https://www.googleapis.com/auth/drive
Run Code Online (Sandbox Code Playgroud)

PyDrive 问题 #108中有更多关于这一点的内容,这给了我很多启发。