Подтвердить что ты не робот

Автоматизация процесса проверки pydrive

Я пытаюсь автоматизировать процесс GoogleAuth при использовании библиотеки pydrive (https://pypi.python.org/pypi/PyDrive).

Я установил pydrive и API Google, чтобы мой secret_client.json работал, но для проверки доступа к gdrive требуется веб-аутентификация каждый раз, когда я запускаю свой script:

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 - это просто текстовый файл. Более того, когда я пытаюсь использовать вышеуказанный script, пока я зарегистрирован в другой учетной записи. Он не загружает 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')

Ошибка:

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 выглядит так:

enter image description here

Как я могу использовать pydrive, так что мне не нужно аутентифицироваться каждый раз, когда я его использую?

Как разрешить автоматическую проверку подлинности, чтобы python script с помощью pydrive script загружался только в учетную запись, которая сгенерировала secret_client.json, а не учетную запись, зарегистрированную в настоящее время в интернет-браузере?

4b9b3361

Ответ 1

Во-первых, вы недооцениваете один очень важный момент:

когда я пытаюсь использовать выше script, пока я вошел в другой Счет. Он не загружает eng.txt в мой gdrive, который сгенерирован secret_client.json, но учетная запись, которая была зарегистрирована, когда я авторизация аутентификации

Именно так оно и должно работать. Вы, как разработчик, распространяете client_secret.json с вашим приложением, и этот файл используется PyDrive для аутентификации приложения с помощью Google. Google хочет знать, сколько запросов API выполняется каждым приложением по всем причинам (показатели, оплата учетной записи, аннулирование доступа и т.д.), Поэтому она требует, чтобы приложение выполняло аутентификацию.

Теперь, когда ваше приложение запускает LocalWebserverAuth, он аутентифицирует клиент с помощью Google. Клиент, конечно, является лицом, фактически использующим ваше приложение. В этом случае разработчик и клиент - это один и тот же человек (вы), но представьте, что вы хотите распространять свое приложение на миллион разных людей. Они должны иметь возможность аутентифицироваться и загружать файлы в свою собственную учетную запись на Диске, а это означает, что все они попадают в ваш (разработчик), который предоставил client_secret.json.

Тем не менее, это действительно очень незначительные изменения, чтобы сделать это, поэтому вашему приложению не нужно просить клиента аутентифицироваться каждый раз при запуске приложения. Вам просто нужно использовать LoadCredentialsFile и SaveCredentialsFile.

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

Ответ 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 будет сгенерирован в рабочем каталоге с токеном обновления.

Этот метод работает лучше, если вы пытаетесь автоматизировать ваш скрипт на сервере

Ответ 3

Весь этот поток мне очень помог, но после того, как я реализовал все представленные здесь решения, появилась еще одна проблема: LocalWebserverAuth() не получит токен обновления.

Если вы откроете "mycreds.txt", сгенерированный после реализации кода @dano, вы увидите, что для "токена обновления" будет установлено значение "null". Через пару часов срок действия токена истекает, и вы получаете следующее, и в конечном итоге вам приходится снова вручную проходить аутентификацию.

Ошибка:

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

Решение для этого состоит в том, чтобы принудительно установить Appro_promt и отключить access_type для параметров потока GoogleAuth.

Вот как я не получил больше ошибок:

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)

Спасибо вам всем!

Ответ 4

Если учетные данные отсутствуют, этот код создает поле ввода с двумя параметрами:

  • Проверка подлинности браузера (что нужно сделать только один раз)

  • Загрузка файла учетных данных (этот файл будет создан в первый раз, когда вы выбираете аутентификацию браузера)

Теперь легко поделиться записной книжкой, которая будет работать без запроса авторизации, поскольку она будет использовать учетные данные, сохраненные в mycreds.txt из локальной среды. Однако, если среда выполнения падает или сбрасывается, этот файл будет утерян, и его нужно будет снова вставить через поле ввода выше. Конечно, вы можете сделать это снова через проверку подлинности браузера, но если вы перераспределяете mycreds.txt людям, использующим ноутбук, они могут использовать функцию Upload для вставки учетных данных в локальную среду.

Последние несколько строк просто предоставляют пример того, как 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')

Ответ 5

Это просто для завершения поста @wang892 выше (у меня недостаточно репутации, чтобы комментировать).

Этот ответ помог мне автоматизировать мой сценарий (без необходимости повторной проверки подлинности при каждом запуске).

Но поскольку я использовал образец файла settings.yaml, доступный в документации PyDrive, я столкнулся с проблемами (из-за моего полного незнания о том, как работает oauth).

Этот пример файла содержит следующие строки, которые, я думаю, ограничивают мой скрипт PyDrive доступом только к файлам и папкам, созданным им самим (подробности см. В выпуске № 122 PyDrive):

Ограниченный доступ:

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

Когда я изменил эти строки, проблема была решена (мне пришлось удалить свои сохраненные учетные данные и запустить скрипт, чтобы повторно авторизовать его, просто еще раз).

Благодаря этим новым строкам мой скрипт теперь имеет доступ ко всем файлам на моем Google Диске:

Полный доступ:

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

Немного больше об этом в выпуске № 108 PyDrive, который меня очень порадовал.