Вопрос по javascript, oauth-2.0, google-drive-sdk – Авторизация Google Диска с использованием JavaScript

41

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

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

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 и Use OAuth 2.0 Credentials клиентский секрет, кажется, является параметром, это должно войти в конфигурацию?

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

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

draw.io/js/diagramly/GoogleDrive.js являетсяNot Found stackunderflow
Ваша ссылка на github устарела - вы можете обновить ее, пожалуйста? Mogsdad

Ваш Ответ

2   ответа
12

<!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 :)

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

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

Я не знаю сейчас, это решение 2012 года :(
Будет ли это решение работать в приложении или расширении Chrome?
Я активировал все службы, все еще получающие доступ не настроен. Пожалуйста, используйте консоль разработчика Google для активации API для вашего проекта.
Возможно тестирование на локальном ПК. Зарегистрируйте mylocalpc.example.com в качестве источника Javascript в консоли API. Отредактируйте ваш / etc / hosts (или любой другой эквивалентный windoze), чтобы добавить mylocalpc.example.com после записи для 127.0.0.1. Я запускаю свои локальные тесты из тестовый сервер GAE, поэтому мне нужно было включить порт 8888 как часть исходного URL-адреса Javascript, т.е. & Quot;mylocalpc.example.com:8888& Quot;
55

но вы должны знать, что есть некоторые болевые точки.

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

Authorization

Во-первых, если вы внимательно посмотрите, как работает аутентификация Google Диска, вы поймете, что после того, как пользователь установил ваше приложение Drive и попытается открыть файл или создать новый файл с вашим приложением, Drive автоматически инициирует поток авторизации OAuth 2.0 и параметры аутентификации установлены наresponse_type=code а такжеaccess_type=offline. This basically means that right now Drive apps are forced to use the OAuth 2 server-side flow which is not going to be of any use to the Javascript client library (which only uses the client-side flow).

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

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

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

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

Handling file content

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

Reading the file content

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

Uploading file content

ОБНОВЛЕНИЕ ОБНОВЛЕНИЕ: конечные точки загрузкиdo теперь поддерживаю CORS.

~~ ОБНОВЛЕНИЕ: конечные точки загрузки, в отличие от остальной части Drive API, не поддерживают CORS, поэтому вам пока придется воспользоваться приведенным ниже приемом: ~~

Загрузка файла является сложной задачей, поскольку он не является встроенным в клиентскую библиотеку Javascript, и вы не можете полностью сделать это с помощью HTTP, как описано вэтот ответ потому что мы не разрешаем междоменные запросы на этих конечных точках API. Таким образом, вам необходимо воспользоваться прокси-сервером iframe, используемым нашей клиентской библиотекой Javascript, и использовать его для отправки составного многокомпонентного запроса в Drive 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);
  }
}

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

Let developers choose which OAuth 2.0 flow they want to use (server-side or client-side) or let the developer handle the OAuth flow entirely. Allow CORS on the /upload/... endpoints Allow CORS on the exportLinks for native gDocs We should make it easier to upload files using our Javascript client library.

Никаких обещаний на данный момент, хотя :)

Быть способным выбрать поток было бы здорово. ETA на это было бы еще больше!
ОБНОВЛЕНИЕ: CORS, похоже, не работает с / upload / endpoints. документируя это сейчас.
@ Давид Я обновил свой ответ об использовании клиентской библиотеки Javascript, так как понял, что для большинства проблем могут быть обходные пути. Дайте мне знать, если у вас все еще есть вопросы.
ОБНОВЛЕНИЕ: Мы включили CORS для URL загрузки (что-то вроде 2-3 недели назад). Я изменяю ответ
ОБНОВЛЕНИЕ: Вы можете использовать параметр? Access_token = ... URL для авторизации по URL загрузки, что упрощает загрузку или потоковую передачу личных файлов на диск.

Похожие вопросы