2

我正在尝试将 Google API 集成到一个项目(论文项目)中,但我有一些疑问和问题。所以,这里是场景:

我用 Java 编写了一个后端应用程序,它只从命令行运行,并且完全没有与用户交互。它的目标是允许传感器和执行器之间的通信和交互。一切都很好。现在我想整合一些东西,以便让传感器以一定的周期性和由于一些检测到的阈值来备份数据。所以我想,为什么不尝试使用 Google Drive。第一个非常有用的链接是:

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

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

快速入门示例就像一个魅力。然而,它需要相当多的设置:在开发者控制台中创建一个项目(因此是一个帐户),启用 Drive API,然后创建一个客户端 ID 和一个客户端密码。完成这些步骤后,您可以硬编码客户端 ID 和密码以形成 google drive 的请求 URL。然后请您在浏览器中输入 url,如果没有,请登录,接受并最后将授权代码复制并粘贴到您的控制台中以获取访问令牌。哇,相当安全的过程。但是,嘿,我完全同意这一点,尤其是在我们拥有需要用户身份验证和授权的网络应用程序、智能手机应用程序或网络服务的情况下,以便让应用程序通过访问其他帐户来完成其工作. 但就我而言,我只是希望传感器能够备份我的谷歌驱动器上的数据。

这些事实引出了我的第一个问题:为了使用 Google API(在本例中为 Drive),我是否必须创建一个项目?还是有其他方法?如果我没记错的话,没有其他方法可以创建客户端 ID 和密码,而无需在开发者控制台中创建项目。这让我很困惑。为什么我应该创建一个项目来使用一些库?

因此,让我们假设前面的约束是合理的,然后继续讨论真正的问题:如何自动化身份验证过程?鉴于我的传感器(只是一个 Java 模块)想要备份数据的场景,不可能完成所有这些步骤。关于 OAuth 2.0 的谷歌页面对我们可以嵌入身份验证过程的不同场景有很好的解释,包括“输入能力有限的设备”。不幸的是,这比其他的更复杂,并且要求“用户切换到具有更丰富输入功能的设备或计算机,启动浏览器,导航到有限输入设备上指定的 URL,登录并输入代码。 " (哈哈)

所以,我没有放弃,最后我写了这篇关于 OAuth Playground 的帖子:如何在没有用户干预的情况下授权应用程序(Web 或已安装)?(规范?)。对我来说,它确实看起来像是一个解决方案,尤其是当它说:

NB2。如果您想要一个访问您自己(并且只有您自己)Drive 帐户的 Web 应用程序,这种技术很有效,而无需编写只能运行一次的授权代码。只需跳过第 1 步,在第 5 步中将“my.drive.app”替换为您自己的电子邮件地址。

但是,如果我没记错的话,我认为 OAuth Playground 只是用于帮助测试和调试使用 Google API 的项目,不是吗?此外,Google 驱动类如GoogleAuthorizationCodeFlowGoogleCredential(在 Java 快速入门示例中使用)总是需要 Client ID、Client Secret 等,这使我归零(创建一个项目并执行整个图形过程)。

总之:有没有一种方法可以避免“图形”身份验证交互并将其转换为仅使用 Drive 的 API 而无需用户干预的自动化过程?非常感谢,我将不胜感激任何提示,提示,答案,指针:-)

4

2 回答 2

3

这只是我根据 pinoyyid 建议编写的代码片段。只是回顾一下在这种情况下我们应该做什么(当您的程序中没有完成所有 Google GUI 身份验证过程的用户交互时)。如https://developers.google.com/drive/web/quickstart/quickstart-java中所述

  1. 转到 Google 开发者控制台。
  2. 选择一个项目,或创建一个新项目。
  3. 在左侧边栏中,展开 APIs & auth。接下来,单击 API。在 API 列表中,确保 Drive API 的状态为 ON。
  4. 在左侧边栏中,选择凭据。

无论哪种情况,您最终都会进入“凭据”页面,并且可以从此处创建项目的凭据。

在凭据页面中,单击 OAuth 标题下的创建新客户端 ID 以创建您的 OAuth 2.0 凭据。您的应用程序的客户端 ID、电子邮件地址、客户端密码、重定向 URI 和 JavaScript 源位于Web 应用程序的客户端 ID部分。

pinoyyd 的帖子更简洁,直截了当: 如何在没有用户干预的情况下授权后台 Web 应用程序?(规范?) 注意第 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

希望这段代码能帮助其他面临同样情况的人!

于 2015-03-20T11:02:14.087 回答
1

我在如何在没有用户干预的情况下授权应用程序(Web 或已安装)?(规范?)

它所描述的确实是您的用例的解决方案。您错过的关键部分是第 7 步,您将自己的应用程序的详细信息输入到 OAuth Playground 中。从那时起,playground 正在模拟您的应用程序,因此您可以进行一次性授权并获取刷新令牌。

于 2015-01-30T06:40:38.240 回答