Google Analytics 3.0身份验证流程

时间:2012-12-06 17:09:23

标签: java google-api oauth-2.0 google-analytics-api google-api-java-client

编辑:最初这个问题询问我如何仅使用我的API密钥对Google AnalyticsAPI进行身份验证。如vlatko pointed out,这是不可能的。现在我只专注于让OAuth2工作。当我有机会时我会尝试vlatko的建议,并会更新问题。与此同时,随意为您认为我缺少的任何事情提供答案。


原始问题:

我正在尝试向Google AnalyticsAPI发出请求。我正在试图复制这些步骤的Hello Analytics教程。无论我尝试什么,我似乎都无法成功验证。

教程说明如下:

  

打开您创建的名为HelloAnalyticsApi.java的文件并添加   以下方法:

private static Analytics initializeAnalytics() throws Exception {
    // Authorization.
    Credential credential = OAuth2Native.authorize(
        HTTP_TRANSPORT, JSON_FACTORY, new LocalServerReceiver(),
        Arrays.asList(AnalyticsScopes.ANALYTICS_READONLY));

    // Set up and return Google Analytics API client.
    return Analytics.builder(HTTP_TRANSPORT, JSON_FACTORY)
        .setApplicationName("Google-Analytics-Hello-Analytics-API-Sample")
        .setHttpRequestInitializer(credential)
        .build();
  }
     

当用户遇到此脚本时,应用程序将尝试执行此操作   打开默认浏览器并将用户导航到托管的URL   google.com。此时,将提示用户登录和   授予应用程序访问其数据的权限。一旦被授予,   应用程序将尝试从浏览器窗口中读取代码   关上窗户。

不同之处在于我正在尝试使用servlet应用程序执行此操作,并且我希望使用API​​密钥(而不是OAuth 2.0客户端ID)进行简单的API访问。我知道建议使用OAuth 2.0,但我只需要访问我拥有的数据并希望简化技术要求。我根据this page做出了这个决定,其中说:

  

API密钥是您使用控制台生成的唯一密钥。什么时候   您的应用程序需要调用在此项目中启用的API,   应用程序将此密钥作为key={API_key}传递给所有API请求   参数。使用此密钥不需要任何用户操作或   同意,不授予访问任何帐户信息的权限,而不是   用于授权。

     

如果您只调用不需要用户数据的API,例如   谷歌自定义搜索API,然后API键可能更简单   实行。但是,如果您的应用程序已使用OAuth 2.0   访问令牌,那么也不需要生成API密钥。在   事实上,如果有OAuth 2.0访问令牌,Google会忽略已传递的API密钥   已经与相应的项目相关联。

我无法使用API​​密钥找到许多auth流程的代码示例 - 我发现的大部分内容都使用客户端ID和下载的.p12文件显示,例如GoogleCredential javadoc。我能找到的一个示例应用是Google的Books Sample应用。无论如何,这是我尝试的(模仿教程中的第一个请求,它从管理API获取帐户列表):

Analytics analytics =
        new Analytics.Builder(httpTransport, jsonFactory, null)
        .setApplicationName("Dev API Access")
        .build();
Management.Accounts.List list =
        analytics.management().accounts().list().setKey(apiKey);
Accounts accounts = list.execute();

“Dev API Access”是我的API控制台信息中心中的“名称”字段。 API密钥是仅限于我的IP地址的服务器密钥。这会因以下响应而失败:

401 Unauthorized
{
  "code": 401,
  "errors": [
    {
      "domain": "global",
      "location": "Authorization",
      "locationType": "header",
      "message": "Login Required",
      "reason": "required"
    }
  ],
  "message": "Login Required"
}

我也试过这个:

Analytics analytics =
        new Analytics.Builder(httpTransport, jsonFactory, null)
        .setApplicationName("Dev API Access")
        .setGoogleClientRequestInitializer(new AnalyticsRequestInitializer(apiKey))
        .build();

Management.Accounts.List list = analytics.management().accounts().list();
Accounts accounts = list.execute();

显示相同的错误。我在这做错了什么?分析调用需要OAuth2吗?如果是这样,为什么只使用API​​示例应用程序中的API密钥?


继续,我继续尝试OAuth2 - 我创建了一个客户端ID并下载了.p12私钥文件。但我也无法做到这一点。这是我试过的:

Credential credential =
        new GoogleCredential.Builder()
        .setTransport(httpTransport)
        .setJsonFactory(jsonFactory)
        .setServiceAccountId(serviceAccountId)
        .setServiceAccountScopes(AnalyticsScopes.ANALYTICS_READONLY)
        .setServiceAccountPrivateKeyFromP12File(new File(p12FilePath))
        .setServiceAccountUser(serviceAccountUser)
        .build();

Analytics analytics =
        new Analytics.Builder(httpTransport, jsonFactory, credential)
        .setApplicationName("Dev API Access")
        .build();

Management.Accounts.List list = analytics.management().accounts().list();
Accounts accounts = list.execute();

serviceAccountId是拥有项目的Google帐户的电子邮件地址,serviceAccountUser是生成的客户ID上列出的电子邮件地址。这失败了以下内容:

400 Bad Request
{
  "error": "invalid_grant"
}

“无效授权”是什么意思,如何成功进行身份验证(理想情况下没有OAuth2)?

2 个答案:

答案 0 :(得分:3)

回答您的第一个问题:通常,OAuth2.0用于授权访问用户的私有数据,因此需要获得用户同意并获取访问令牌。但是,对于Google Books API,如果您正在访问公共数据,则无需最终用户同意,因此API密钥就足够了。如果您尝试使用Books API访问非公开数据,则仍需要OAuth2令牌。

您的案例的好消息是,即使使用OAuth2,您也可以绕过用户参与并使用服务帐户简化流程 - 假设您的应用程序可以访问API。有一种方法可以为Analytics API进行设置,解释here(请查看“服务帐户”部分中的步骤)。我认为您与Credential构建器处于正确的轨道上,但我认为您不需要在那里设置服务帐户用户,因为您没有进行任何用户模拟。

答案 1 :(得分:3)

vlatko's answer让我走上正轨。问题原来是我将所有者电子邮件地址与服务帐户电子邮件地址混淆。例如,我正在做以下事情:

Credential credential =
    new GoogleCredential.Builder()
    .setTransport(httpTransport)
    .setJsonFactory(jsonFactory)
    .setServiceAccountId("owneremail@gmail.com")                   //wrong
    .setServiceAccountScopes(AnalyticsScopes.ANALYTICS_READONLY)
    .setServiceAccountPrivateKeyFromP12File(new File(p12FilePath))
    .setServiceAccountUser("xxx@developer.gserviceaccount.com")    //unnecessary
    .build();

当我需要这样做时:

Credential credential =
    new GoogleCredential.Builder()
    .setTransport(httpTransport)
    .setJsonFactory(jsonFactory)
    .setServiceAccountId("xxx@developer.gserviceaccount.com")
    .setServiceAccountScopes(AnalyticsScopes.ANALYTICS_READONLY)
    .setServiceAccountPrivateKeyFromP12File(new File(p12FilePath))
    .build();

此外,我在我的Google Analytics应用程序中添加了owneremail@gmail.com用户 - 这同样需要成为服务帐户电子邮件。