Google 表格使用 API 键而不是 client_secret.json

Google Sheets use API key instead of client_secret.json

Java QuickstartQuickStart.java 示例中,他们使用 OAuth client ID 来识别应用程序,这会弹出 windows 要求 Google 凭据使用该应用程序。你得下载一个client_secret.json修改一个GoogleSheet.

我的问题是:您能否使用 API Key 或其他方式来避免弹出的 window 请求 Google 凭据?而且,如果可能的话,您如何更改 Java 代码才能做到这一点?

您看到的 window 弹出窗口是 Oauth2 同意屏幕。要访问私人用户数据,您需要征得用户同意才能访问他们的数据。

还有一个选项叫做服务帐户。如果您尝试访问的 sheet 是您作为开发人员可以控制的,那么您可以创建服务帐户凭据,获取服务帐户电子邮件地址并授予服务帐户对 sheet 的访问权限。

据我所知,使用 java 访问服务帐户的最佳示例是 Google Analytics,您必须将其更改为 Google sheet如果您有任何问题,我可以提供帮助。 hello analytics service account.

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;

import com.google.api.services.analytics.Analytics;
import com.google.api.services.analytics.AnalyticsScopes;
import com.google.api.services.analytics.model.Accounts;
import com.google.api.services.analytics.model.GaData;
import com.google.api.services.analytics.model.Profiles;
import com.google.api.services.analytics.model.Webproperties;

import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.io.IOException;


/**
 * A simple example of how to access the Google Analytics API using a service
 * account.
 */
public class HelloAnalytics {


  private static final String APPLICATION_NAME = "Hello Analytics";
  private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
  private static final String KEY_FILE_LOCATION = "<REPLACE_WITH_JSON_FILE>";
  public static void main(String[] args) {
    try {
      Analytics analytics = initializeAnalytics();

      String profile = getFirstProfileId(analytics);
      System.out.println("First Profile Id: "+ profile);
      printResults(getResults(analytics, profile));
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * Initializes an Analytics service object.
   *
   * @return An authorized Analytics service object.
   * @throws IOException
   * @throws GeneralSecurityException
   */
  private static AnalyticsReporting initializeAnalytic() throws GeneralSecurityException, IOException {

    HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
    GoogleCredential credential = GoogleCredential
        .fromStream(new FileInputStream(KEY_FILE_LOCATION))
        .createScoped(AnalyticsScopes.all());

    // Construct the Analytics service object.
    return new Analytics.Builder(httpTransport, JSON_FACTORY, credential)
        .setApplicationName(APPLICATION_NAME).build();
  }


  private static String getFirstProfileId(Analytics analytics) throws IOException {
    // Get the first view (profile) ID for the authorized user.
    String profileId = null;

    // Query for the list of all accounts associated with the service account.
    Accounts accounts = analytics.management().accounts().list().execute();

    if (accounts.getItems().isEmpty()) {
      System.err.println("No accounts found");
    } else {
      String firstAccountId = accounts.getItems().get(0).getId();

      // Query for the list of properties associated with the first account.
      Webproperties properties = analytics.management().webproperties()
          .list(firstAccountId).execute();

      if (properties.getItems().isEmpty()) {
        System.err.println("No Webproperties found");
      } else {
        String firstWebpropertyId = properties.getItems().get(0).getId();

        // Query for the list views (profiles) associated with the property.
        Profiles profiles = analytics.management().profiles()
            .list(firstAccountId, firstWebpropertyId).execute();

        if (profiles.getItems().isEmpty()) {
          System.err.println("No views (profiles) found");
        } else {
          // Return the first (view) profile associated with the property.
          profileId = profiles.getItems().get(0).getId();
        }
      }
    }
    return profileId;
  }

  private static GaData getResults(Analytics analytics, String profileId) throws IOException {
    // Query the Core Reporting API for the number of sessions
    // in the past seven days.
    return analytics.data().ga()
        .get("ga:" + profileId, "7daysAgo", "today", "ga:sessions")
        .execute();
  }

  private static void printResults(GaData results) {
    // Parse the response from the Core Reporting API for
    // the profile name and number of sessions.
    if (results != null && !results.getRows().isEmpty()) {
      System.out.println("View (Profile) Name: "
        + results.getProfileInfo().getProfileName());
      System.out.println("Total Sessions: " + results.getRows().get(0).get(0));
    } else {
      System.out.println("No results found");
    }
  }
}

API 密钥只能在访问创建该密钥的项目所拥有的资源时起作用。

对于电子表格等资源,您通常会访问 用户 拥有的资源。如果 you 仅通过 API 密钥就可以访问 my 私人表格,那就太糟糕了。

所以不,我不希望有任何方法可以避免获得使用用户文档的授权。但是,您应该能够使用 Java OAuth library 来保留身份验证令牌,这样您就可以避免多次请求它。 (当然,除非用户撤销访问权限。)

正如 DalmTo 所说,如果您尝试访问项目拥有的资源(或项目可以被授予访问权限的资源),则可以使用服务帐户凭据。请注意,如果您 运行 AppEngine、Google Kubernetes Engine 或 Google Compute Engine,则该环境的服务帐户凭据应该自动可用。