API Google Диска — OAuth2.0: как автоматизировать процесс аутентификации? Сомнения и вопросы

Я пытаюсь интегрировать API Google в проект (проект Thesis), и у меня есть некоторые сомнения и вопросы. Итак, вот сценарий:

Я написал внутреннее приложение на Java, которое запускается исключительно из командной строки и абсолютно не взаимодействует с пользователем. Его цель — обеспечить связь и взаимодействие между датчиками и исполнительными механизмами. Все отлично работает. Теперь хотелось бы кое-что интегрировать, чтобы датчики бэкапили данные как с определенной периодичностью, так и по определенному пороговому значению. Поэтому я подумал, почему бы не попробовать с Google Диском. Первыми очень полезными ссылками были:

https://developers.google.com/drive/web/quickstart/quickstart-java

https://developers.google.com/accounts/docs/OAuth2InstalledApp

Примеры быстрого запуска работают как шарм. Однако для этого требуется довольно много настроек: создайте проект в консоли разработчика (следовательно, учетную запись), включите Drive API, затем создайте идентификатор клиента и секрет клиента. Выполнив эти шаги, вы можете жестко закодировать идентификатор клиента и секрет, чтобы сформировать URL-адрес запроса для диска Google. Затем вас попросят ввести URL-адрес в браузере, авторизоваться, если это не так, принять и, наконец, скопировать и вставить в консоль код авторизации для получения токена доступа. Вау, довольно безопасный процесс. Но, эй, я полностью согласен с этим, прежде всего в сценарии, когда у нас есть веб-приложение, приложение для смартфона или веб-служба, которая требует аутентификации и авторизации пользователей, чтобы позволить приложению выполнять свою работу путем доступа чужой аккаунт. Но в моем случае я просто хотел бы, чтобы датчики создавали резервные копии данных на моем диске Google.

Эти факты приводят к моему первому вопросу: чтобы использовать API Google (в данном случае Drive), нужно ли мне в любом случае создавать проект? Или есть другой подход? Если я не ошибаюсь, нет других способов создать идентификатор клиента и секрет без создания проекта в консоли разработчика. Это меня очень озадачивает. Почему я должен создавать проект, чтобы использовать в основном некоторые библиотеки?

Итак, давайте примем предыдущее как оправданные ограничения и перейдем к реальному вопросу: как автоматизировать процесс аутентификации? Учитывая мой сценарий, когда датчик (просто модуль Java) хочет сделать резервную копию данных, было бы невозможно выполнить все эти шаги. На странице Google, посвященной OAuth 2.0, есть отличные пояснения о различных сценариях, в которые мы можем внедрить процедуру аутентификации, в том числе для "устройств с ограниченными возможностями ввода". К сожалению, это сложнее, чем другие, и требует, чтобы "Пользователь переключался на устройство или компьютер с более широкими возможностями ввода, запускал браузер, переходил по URL-адресу, указанному на устройстве с ограниченным вводом, входил в систему. и вводит код." (LOL)

Итак, я не сдался и попал в этот пост, в котором рассказывается об OAuth Playground: Как мне авторизовать приложение (веб-приложение или установленное) без вмешательства пользователя? (канонический?). Это действительно похоже на решение для меня, в частности, когда он говорит:

NB2. Этот метод хорошо работает, если вы хотите, чтобы веб-приложение имело доступ к вашей собственной (и только вашей) учетной записи на Диске, не утруждая себя написанием кода авторизации, который будет запускаться только один раз. Просто пропустите шаг 1 и замените "my.drive.app" на свой адрес электронной почты на шаге 5.

Однако, если я не ошибаюсь, я думаю, что OAuth Playground просто помогает тестировать и отлаживать проекты, использующие API Google, не так ли? Более того, классы дисков Google, такие как GoogleAuthorizationCodeFlow и GoogleCredential (используемые в примере быстрого запуска Java), всегда нуждаются в клиенте. ID, Client Secret и так далее, что приводит меня к нулевой точке (создать проект и выполнить всю графическую процедуру).

В заключение: есть ли способ избежать «графического» взаимодействия аутентификации и преобразовать его в автоматизированный процесс, используя только API-интерфейсы Drive без вмешательства пользователя? Спасибо большое, буду благодарен за любую подсказку, подсказку, ответ, указку :-)


person DemoomeD534    schedule 29.01.2015    source источник


Ответы (2)


Я написал сообщение SO по адресу Как сделать Я разрешаю приложение (веб-сайт или установленное) без вмешательства пользователя? (канонический?)

То, что он описывает, действительно является решением для вашего варианта использования. Ключевым моментом, который вы пропустили, является шаг 7, когда вы вводите данные своего собственного приложения в OAuth Playground. С этого момента игровая площадка выдает себя за ваше приложение, поэтому вы можете выполнить однократную авторизацию и получить токен обновления.

person pinoyyid    schedule 30.01.2015
comment
Привет пинойид. Спасибо за ответ. Есть еще деталь, которую мне не хватает. В конфигурации OAuth Playground выше, где я должен ввести идентификатор клиента и секретировать, написано: Вам нужно будет указать URL-адрес developers.google.com/oauthplayground в качестве действительного URI перенаправления в вашем проекте Google API Console. Затем введите идентификатор клиента и секрет, назначенный веб-приложению в вашем проекте ниже... . Честно говоря, я думал, что должен создать идентификатор клиента для установленных приложений, а не для веб-приложения, я ошибаюсь? Потому что в первом случае я не могу ввести какой-либо редирект uri в свой проект. - person DemoomeD534; 30.01.2015
comment
идентификаторы клиентов довольно переносимы между типами приложений, так что в этом нет ничего страшного. После того, как вы выиграли жетон обновления, вы дома. Тот факт, что вы выиграли токен обновления с помощью веб-приложения, но затем используете его из установленного приложения, не является проблемой. - person pinoyyid; 30.01.2015
comment
Ок, отлично. Это означает, что я должен проверить, когда истек срок действия токена доступа, и просто отправить HTTPS-запрос POST в googleapis. com/oauth2/v3/token, включив идентификатор клиента, секрет, refresh_token и grant_type, не так ли? Более того, я считаю, что я также должен проверять токены обновления, поскольку у меня где-то около 20 и 30 датчиков, а количество токенов обновления ограничено, как указано в developers.google.com/accounts/docs/OAuth2WebServer#refresh - person DemoomeD534; 30.01.2015
comment
Ага. По какой причине вы создаете Refresh Token для каждого датчика? Нет никаких причин, по которым они не могут использовать один и тот же RT. - person pinoyyid; 30.01.2015
comment
Большое спасибо, пинойид, я очень ценю это. Насчет токена обновления для каждого датчика я до сих пор не уверен. Самый простой способ, безусловно, иметь только один RT для всех. Сейчас попробую что-нибудь закодировать и выложу, когда будет красиво и понятно. Лучший. - person DemoomeD534; 30.01.2015
comment
RT имеет срок действия? - person str028; 19.11.2019

Это всего лишь фрагмент кода, который я написал благодаря предложениям пинойида. Просто напомним, что мы должны делать в этом случае (когда в вашей программе нет взаимодействия с пользователем для завершения всего процесса аутентификации Google GUI). Как сообщается в https://developers.google.com/drive/web/quickstart/quickstart-java

  1. Перейдите в консоль разработчиков Google.
  2. Выберите проект или создайте новый.
  3. На боковой панели слева разверните API и авторизация. Затем нажмите API. Убедитесь, что в списке API-интерфейсов включен статус Drive API.
  4. На боковой панели слева выберите Учетные данные.

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

На странице «Учетные данные» нажмите «Создать новый идентификатор клиента» под заголовком «OAuth», чтобы создать свои учетные данные OAuth 2.0. Идентификатор клиента вашего приложения, адрес электронной почты, секрет клиента, URI перенаправления и источники JavaScript находятся в разделе Идентификатор клиента для веб-приложения.

Сообщение pinoyyd более аккуратное и сразу переходит к делу: -canonical"> Как авторизовать фоновое веб-приложение без вмешательства пользователя? (канонический?) Обратите внимание на шаг 7

Наконец, фрагмент кода очень прост, он просто отправляет запрос POST, и в Java это можно сделать разными способами. Поэтому это всего лишь пример, и я уверен, что есть место для улучшений ;-)

// Both to set access token the first time that we run the module and in general to refresh the token
public void sendPOST(){
  try {
      URL url = new URL("https://www.googleapis.com/oauth2/v3/token");
      Map<String,Object> params = new LinkedHashMap<>();
      params.put("client_id", CLIENT_ID);
      params.put("client_secret", CLIENT_SECRET);
      params.put("refresh_token", REFRESH_TOKEN);
      params.put("grant_type", "refresh_token");

      StringBuilder postData = new StringBuilder();
      for (Map.Entry<String,Object> param : params.entrySet()) {
          if (postData.length() != 0) postData.append('&');
          postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
          postData.append('=');
          postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
      }
      byte[] postDataBytes = postData.toString().getBytes("UTF-8");

      HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
      conn.setRequestMethod("POST");
      conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
      conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
      conn.setDoOutput(true);
      conn.getOutputStream().write(postDataBytes);

      BufferedReader in_rd = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));

      // Read response body which should be a json structure
      String inputLine;
      StringBuilder responseBody = new StringBuilder();

      while ((inputLine = in_rd.readLine()) != null) {
              responseBody.append(inputLine);
      }
      in_rd.close();

      //Parsing Response --> create a json object
      JSONObject jsonResp = new JSONObject(responseBody);

      //Modify previous access token String
      ACCESS_TOKEN = jsonResp.getString("access_token");

  }

  catch(MalformedURLException ex_URL){
      System.out.println("An error occured: " + ex_URL.getMessage());
  }
  catch(JSONException ex_json) {
      System.out.println("An error occured: " + ex_json.getMessage());             
  }
  catch(IOException ex_IO){
      System.out.println("An error occured: " + ex_IO.getMessage());
  }

} //end of sendRefreshPOST method

Надеюсь, этот фрагмент кода поможет другим, которые столкнутся с такой же ситуацией!

person DemoomeD534    schedule 20.03.2015