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

Авторизация Google Диска с использованием JavaScript

Я пытаюсь разрешить мое приложение интегрироваться с Google Диском. Документация Google содержит подробные сведения о авторизации на сервере и примеры кода для различных серверных технологий.

Также существует JavaScript API API Google, которая имеет поддержку авторизации. В разделе образцов вики есть фрагмент кода для создания конфигурации и вызова authorize. Я изменил область действия, которую я считаю необходимой для диска:

var config = {
    'client_id': 'my_client_ID',
    'scope': 'https://www.googleapis.com/auth/drive.file'
  };
  gapi.auth.authorize(config, function() {
    console.log(gapi.auth);
  });

Функция обратного вызова никогда не вызывается (да, библиотека Google API загружена исправлена). Посмотрите пример Java Retrieve and Use OAuth 2.0 Credentials, клиентский секрет кажется параметром, если это входит в конфигурацию?

Кто-нибудь пробовал это в JS, для Диска или других API Google? Кто-нибудь знает лучший маршрут для отладки такой проблемы, т.е. Мне нужно просто пройти через библиотеку и остановить whinging?

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

4b9b3361

Ответ 1

Можно использовать клиентскую библиотеку Javascript API Google API с Диском, но вы должны знать, что есть некоторые болевые точки.

В настоящее время существует 2 основных вопроса, оба из которых имеют рабочий объём:

Авторизация

Сначала, если вы внимательно посмотрите, как работает Google Drive, вы поймете, что после того, как пользователь установил ваше приложение на Диске и попытается открыть файл или создать новый файл с вашим приложением, Drive инициирует авторизацию OAuth 2.0 автоматически, а для параметров auth установлены response_type = code и access_type = offline. Это в основном означает, что прямо сейчас приложениям Drive принудительно использовать серверный поток OAuth 2, который не будет полезен для клиентской библиотеки Javascript (который использует только поток на стороне клиента).

Проблема в том, что: Drive инициирует поток OAuth 2.0 на стороне сервера, тогда клиентская библиотека Javascript инициирует поток OAuth 2.0 на стороне клиента.

Это все еще может работать, все, что вам нужно сделать, это использовать код на стороне сервера для обработки кода авторизации, возвращаемого после потока на стороне сервера (вам необходимо обменивать его на токен доступа и токен обновления). Таким образом, только в первом потоке пользователь получит запрос на авторизацию. После первого обмена кодом авторизации автоматически откроется страница auth.

Сэмплы на стороне сервера для этого доступны в нашей документации.

Если вы не обрабатываете и не обмениваете код авторизации на потоке на стороне сервера, пользователю будет предложено выполнить авторизацию каждый раз, когда он попытается использовать ваше приложение на Диске.

Обработка содержимого файла

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

Чтение содержимого файла

Когда метаданные файла/объект файла извлекаются, он содержит атрибут downloadUrl, который указывает на фактическое содержимое файла. Теперь можно загрузить файл, используя запрос CORS, и самый простой способ auth - использовать токен доступа OAuth 2 в параметре URL. Поэтому просто добавьте &access_token=... в downloadUrl и извлеките файл с помощью XHR или перенаправляя пользователя на URL.

Загрузка содержимого файла

UPDATE UPDATE: конечные точки загрузки do теперь поддерживают CORS.

~~ UPDATE: конечные точки загрузки, в отличие от остальной части Drive API, не поддерживают CORS, поэтому вам придется использовать трюк ниже: ~~

Загрузка файла сложна, потому что он не встроен в клиентскую библиотеку Javascript, и вы не можете полностью выполнить это с HTTP, как описано в этом ответе, потому что мы не 't разрешать междоменные запросы на этих конечных точках API. Поэтому вам нужно воспользоваться прокси-сервером iframe, используемым нашей клиентской библиотекой Javascript, и использовать его для отправки сконструированного многостраничного запроса на SDK накопителя. Благодаря @Alain у нас есть пример того, как это сделать ниже:

/**
 * Insert new file.
 *
 * @param {File} fileData File object to read data from.
 * @param {Function} callback Callback function to call when the request is complete.
 */
function insertFileData(fileData, callback) {
  const boundary = '-------314159265358979323846';
  const delimiter = "\r\n--" + boundary + "\r\n";
  const close_delim = "\r\n--" + boundary + "--";

  var reader = new FileReader();
  reader.readAsBinaryString(fileData);
  reader.onload = function(e) {
    var contentType = fileData.type || 'application/octet-stream';
    var metadata = {
      'title': fileData.fileName,
      'mimeType': contentType
    };

    var base64Data = btoa(reader.result);
    var multipartRequestBody =
        delimiter +
        'Content-Type: application/json\r\n\r\n' +
        JSON.stringify(metadata) +
        delimiter +
        'Content-Type: ' + contentType + '\r\n' +
        'Content-Transfer-Encoding: base64\r\n' +
        '\r\n' +
        base64Data +
        close_delim;

    var request = gapi.client.request({
        'path': '/upload/drive/v2/files',
        'method': 'POST',
        'params': {'uploadType': 'multipart'},
        'headers': {
          'Content-Type': 'multipart/mixed; boundary="' + boundary + '"'
        },
        'body': multipartRequestBody});
    if (!callback) {
      callback = function(file) {
        console.log(file)
      };
    }
    request.execute(callback);
  }
}

Чтобы улучшить все это, в будущем мы могли бы:

  • Пусть разработчики выбирают, какой поток OAuth 2.0 они хотят использовать (на стороне сервера или на стороне клиента), или пусть разработчик полностью обрабатывает поток OAuth.
  • Разрешить CORS на конечных точках /upload/...
  • Разрешить CORS для exportLinks для родных gDocs
  • Мы должны упростить загрузку файлов с помощью нашей клиентской библиотеки Javascript.

Нет promises, хотя:)

Ответ 2

Я сделал это. Вот мой код:

<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8' />
    <style>
        p {         
            font-family: Tahoma;
        }
    </style>
  </head>
  <body>
    <!--Add a button for the user to click to initiate auth sequence -->
    <button id="authorize-button" style="visibility: hidden">Authorize</button>
    <script type="text/javascript">
      var clientId = '######';
      var apiKey = 'aaaaaaaaaaaaaaaaaaa';
      // To enter one or more authentication scopes, refer to the documentation for the API.
      var scopes = 'https://www.googleapis.com/auth/drive';

      // Use a button to handle authentication the first time.
      function handleClientLoad() {
        gapi.client.setApiKey(apiKey);
        window.setTimeout(checkAuth,1);
      }

      function checkAuth() {
        gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: true}, handleAuthResult);
      }

      function handleAuthResult(authResult) {
        var authorizeButton = document.getElementById('authorize-button');
        if (authResult && !authResult.error) {
          authorizeButton.style.visibility = 'hidden';
          makeApiCall();
        } else {
          authorizeButton.style.visibility = '';
          authorizeButton.onclick = handleAuthClick;
        }
      }

      function handleAuthClick(event) {
        gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: false}, handleAuthResult);
        return false;
      }

      // Load the API and make an API call.  Display the results on the screen.
      function makeApiCall() {
        gapi.client.load('drive', 'v2', function() {

          var request = gapi.client.drive.files.list ( {'maxResults': 5 } );

          request.execute(function(resp) {          
            for (i=0; i<resp.items.length; i++) {
                    var titulo = resp.items[i].title;
                    var fechaUpd = resp.items[i].modifiedDate;
                    var userUpd = resp.items[i].lastModifyingUserName;

                    var fileInfo = document.createElement('li');
                    fileInfo.appendChild(document.createTextNode('TITLE: ' + titulo + ' - LAST MODIF: ' + fechaUpd + ' - BY: ' + userUpd ));                
                    document.getElementById('content').appendChild(fileInfo);
            }
          });        
        });
      }
    </script>
    <script src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script>    
    <p><b>These are 5 files from your GDrive :)</b></p>
    <div id="content"></div>
  </body>
</html>

Вам нужно только изменить:

  • var clientId = '######';
  • var apiKey = 'aaaaaaaaaaaaaaaaaaa';

на ваш clientID и ApiKey из консоли Google API:)

Конечно, вам нужно создать свой проект в Google API Console, активировать API-интерфейс Drive и активировать учетные записи учетных записей Google в OAuth 2.0 (действительно eeeeasy!)

PS: он не будет работать локально на вашем ПК, он будет работать на каком-то хостинге, а yoy должен предоставить URL-адрес от него на консоли проекта:)