401 访问被拒绝。您无权阅读 activity 条记录

401 Access denied. You are not authorized to read activity records

我正在尝试从报告中获取数据 API。

我获得服务帐户的访问令牌并在 GET 请求中使用它。始终响应

{
  "error": {
    "errors": [
      {
        "domain": "global",
        "reason": "authError",
        "message": "Access denied. You are not authorized to read activity records.",
        "locationType": "header",
        "location": "Authorization"
      }
    ],
    "code": 401,
    "message": "Access denied. You are not authorized to read activity records."
  }
}

我正在使用 Java 请求。没有 Google API 库(客户要求)。源代码是

String urlString = "https://www.googleapis.com/admin/reports/v1/activity/users/all/applications/drive?maxResults=25";

        URL url = new URL(urlString);
        HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();

        // optional default is GET
        urlConnection.setRequestMethod("GET");
        urlConnection.setDoInput(true);

        // Add request header.
        urlConnection.setRequestProperty("Authorization", "Bearer " + accessToken.getValue());

        int responseCode = urlConnection.getResponseCode();

        System.out.println("\nSending 'GET' request to URL : " + urlString);
        System.out.println("Response Code : " + responseCode);

        BufferedReader bufferedReader;

        if (responseCode == 200) {
            bufferedReader = new BufferedReader(
                    new InputStreamReader(urlConnection.getInputStream()));
        } else {
            bufferedReader = new BufferedReader(
                    new InputStreamReader(urlConnection.getErrorStream()));
        }

        String inputLine;
        StringBuffer stringBuffer = new StringBuffer();

        while ((inputLine = bufferedReader.readLine()) != null) {
            stringBuffer.append(inputLine);
        }

        bufferedReader.close();

        System.out.println(stringBuffer.toString());

你能帮我看看我遗漏了什么吗?

此致, 亚历克斯

"Access denied. You are not authorized to read activity records.",

仅表示与您一起进行身份验证的用户无权执行您正在尝试执行的操作。要通过此 api 使用服务帐户,您需要设置 domain wide delegation

In enterprise applications you may want to programmatically access a user's data without any manual authorization on their part. In G Suite domains, the domain administrator can grant third-party applications with domain-wide access to its users' data — this is referred as domain-wide delegation of authority. To delegate authority this way, domain administrators can use service accounts with OAuth 2.0.

  1. Go to your G Suite domain’s Admin console.
  2. Select Security from the list of controls. If you don't see Security listed, select More controls from the gray bar at the bottom of the page, then select Security from the list of controls.
  3. Select Advanced settings from the list of options.
  4. Select Manage third party OAuth Client access in the Authentication section.
  5. In the Client name field enter the service account's Client ID.
  6. In the One or More API Scopes field enter the list of scopes that your application should be granted access to (see image below). For example if you need domain-wide access to activity reports enter: https://www.googleapis.com/auth/admin.reports.audit.readonly
  7. Click the Authorize button.

只是下面的代码。这里有两件事非常重要:电子邮件 ID 即 SERVICE_ACCOUNT_EMAIL 和 json 文件 SERVICE_ACCOUNT_PKCS12_FILE_PATH:

来源:https://developers.google.com/admin-sdk/reports/v1/guides/delegation

我正在使用它的 GO 版本,在它上面花了 2 天后它就像一个魅力:))(顺便说一句,可以在这里找到 GO 版本:https://developers.google.com/admin-sdk/directory/v1/guides/delegation#go

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.admin.reports.Reports;
import com.google.api.services.admin.reports.ReportsScopes;
...

/** Email of the Service Account */
private static final String SERVICE_ACCOUNT_EMAIL = "<some-id>@developer.gserviceaccount.com";

/** Path to the Service Account's Private Key file */
private static final String SERVICE_ACCOUNT_PKCS12_FILE_PATH = "/path/to/<public_key_fingerprint>-privatekey.p12";

/**
 * Build and returns a Reports service object authorized with the service accounts
 * that act on behalf of the given user.
 *
 * @param userEmail The email of the user. Needs permissions to access the Admin APIs.
 * @return Reports service object that is ready to make requests.
 */
public static Reports getReportsService(String userEmail) throws GeneralSecurityException,
    IOException, URISyntaxException {
  HttpTransport httpTransport = new NetHttpTransport();
  JacksonFactory jsonFactory = new JacksonFactory();
  GoogleCredential credential = new GoogleCredential.Builder()
      .setTransport(httpTransport)
      .setJsonFactory(jsonFactory)
      .setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
      .setServiceAccountScopes(ReportsScopes.ADMIN_REPORTS_AUDIT_READONLY)
      .setServiceAccountUser(userEmail)
      .setServiceAccountPrivateKeyFromP12File(
          new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
      .build();
  Reports service = new Reports.Builder(httpTransport, jsonFactory, null)
      .setHttpRequestInitializer(credential).build();
  return service;
}