【问题标题】:Automating pydrive verification process自动化 pydrive 验证过程
【发布时间】:2014-06-25 21:49:00
【问题描述】:

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

我已经设置了 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')

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

在上一篇文章中,我尝试了以下方法来自动化验证过程,但它给出了错误消息:

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')

错误:

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')]

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

如何使用 pydrive,这样我每次使用时都不需要进行身份验证?

如何允许自动认证,使使用pydrive脚本的python脚本只上传到生成secret_client.json的账户,而不是当前在互联网浏览器上登录的账户? p>

【问题讨论】:

    标签: python google-api cloud google-drive-api pydrive


    【解决方案1】:

    首先,您对它的工作原理有一个非常重要的误解:

    当我登录到另一个脚本时尝试使用上述脚本 帐户。它不会将 eng.txt 上传到我生成的 gdrive 中 secret_client.json 但我登录时的帐户 授权认证

    这正是它应该如何工作的。作为开发人员,您将client_secret.json 与您的应用程序一起分发,PyDrive 使用该文件向 Google 验证应用程序。 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')
    

    【讨论】:

    • @Gregg 您仍然需要client_secrets.json 来验证应用程序。 mycreds.txt 将存储可用于对用户进行身份验证的令牌。因此,第一次运行此代码时,您需要通过网络浏览器输入验证码。第二次,它应该使用保存在mycreds.txt 中的凭据。
    • 这让我很开心。谢谢你:)
    • 就像@Joe 一样,你成就了我的一天。我很感激。
    • @dano 你真棒
    • 此方法与@wang892 的方法相比如何?令牌过期后是否需要继续手动授权?
    【解决方案2】:

    另一种方法是通过将 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
    

    有了这个文件,第一次还是要使用浏览器完成认证,之后会在工作目录下生成一个带有刷新令牌的credentials.json文件。

    如果您尝试在服务器上自动执行脚本,则此方法效果更好

    【讨论】:

    • 嗨 - 我刚刚开始使用这些东西 - 按照快速入门并添加您非常有用的建议。我注意到 'setting.yaml' 应该是 'settings.yaml' - 然后效果很好。
    • 谢谢,这就像一个魅力! PyDrive 快速入门指南的细节不太清楚。
    • 您能否提供一些类似于 dano 上面提供的示例的代码,以显示您的身份验证代码的实际工作方式?
    【解决方案3】:

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

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

    错误:

    raise RefreshError('No refresh_token found.') pydrive.auth.RefreshError: No refresh_token found.Please set access_type of OAuth to offline.
    

    解决方案是强制approval_promt 并在GoogleAuth 的流参数上将access_type 设置为offline。

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

    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)
    

    谢谢大家!

    【讨论】:

    • access_type:offline 和approval_prompt:force 的加入让我很开心!非常感谢!太棒了?顺便说一句,Gauth Flow 的文档在哪里?没找到。。
    【解决方案4】:

    这只是为了完成@wang892 post above(我没有足够的声誉来评论)。

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

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

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

    访问受限:

    oauth_scope:
      - https://www.googleapis.com/auth/drive.file
      - https://www.googleapis.com/auth/drive.install
    

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

    有了这些新行,我的脚本现在可以访问我的 Google Drive 中的所有文件:

    完全访问权限:

    oauth_scope:
      - https://www.googleapis.com/auth/drive
    

    PyDrive issue #108 对此有更多的了解,这让我很受启发。

    【讨论】:

      【解决方案5】:

      如果凭据没有到位,此代码会生成一个包含两个选项的输入框:

      • 浏览器身份验证(只需执行一次)

      • 上传凭证文件(该文件将在您选择浏览器身份验证的第一次生成

      现在可以轻松共享 notebook,它无需请求授权即可运行,因为它将使用本地环境中保存在 mycreds.txt 中的凭据。但是,如果运行时崩溃或被重置,该文件将丢失,需要通过上面的输入框重新插入。当然,您可以通过浏览器身份验证再次执行此操作,但如果您将 mycreds.txt 重新分发给使用笔记本的人,他们可以使用上传功能将凭据插入本地环境。

      最后几行仅提供了一个示例,说明如何将来自已验证驱动器的 csv 文件上传并在笔记本中使用。

      #Install the required packages and fix access to my Google drive account
      !pip install pydrive
      from pydrive.auth import GoogleAuth
      from pydrive.drive import GoogleDrive
      from google.colab import auth
      from oauth2client.client import GoogleCredentials
      
      
      #Checks for file with Google authentication key, if the file is not in place, it asks to authenticate via the browser
      gauth = GoogleAuth()
      if os.path.isfile("mycreds.txt") is False:
          choice = input ("Do you want to: U) Upload authentication file (mycreds.txt). B) Browser authentication (only possible for owner of the connected Google drive folder). [U/B]? : ")
          if choice == "U":
                print ("Upload the mycreds.txt file")
                from google.colab import files
                files.upload()      
          elif choice == "B":
                auth.authenticate_user()
                gauth.credentials = GoogleCredentials.get_application_default()
                gauth.SaveCredentialsFile("mycreds.txt")
      
      gauth.LoadCredentialsFile("mycreds.txt")
      if gauth.access_token_expired:
          gauth.Refresh()
      else: gauth.Authorize()
      
      #Now you can easily use the files from your drive by using their ID  
      drive = GoogleDrive(gauth)
      download = drive.CreateFile({'id': '1KRqYpR9cteX-ZIwhdfghju6_wALl4'})
      download.GetContentFile('my_data.csv')
      data_frame = pd.read_csv('my_data.csv')
      

      【讨论】:

      • 这几乎是我需要的,但身份验证部分由于某种原因不起作用。我可以毫无问题地生成 mycreds.txt,但是脚本结束时没有消息并且没有安装谷歌驱动器
      猜你喜欢
      • 2014-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-06
      • 1970-01-01
      • 1970-01-01
      • 2021-09-04
      • 2020-11-05
      相关资源
      最近更新 更多