6

編集:もともと、この質問は、API キーのみを使用して Google アナリティクス API で認証する方法を尋ねていました。vlatkoが指摘したように、これは不可能です。今は、OAuth2 を機能させることに集中しています。機会があればvlatkoの提案を試し、質問を更新します。それまでの間、私が見逃していると思われるものについて、自由に回答を投稿してください。


元の質問:

Google アナリティクス API にリクエストを送信しようとしています。手順を複製しようとして、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();
  }

ユーザーがこのスクリプトに遭遇すると、アプリケーションはデフォルトのブラウザーを開こうとし、ユーザーを google.com でホストされている URL にナビゲートしようとします。この時点で、ユーザーはログインしてアプリケーションにデータへのアクセスを許可するよう求められます。許可されると、アプリケーションはブラウザ ウィンドウからコードを読み取ろうとし、ウィンドウを閉じます。

違いは、サーブレット アプリケーションでこれを実行しようとしており、(OAuth 2.0 クライアント ID ではなく) API キーを使用した単純な API アクセスを使用したいということです。OAuth 2.0 が推奨されていることは知っていますが、自分が所有するデータにのみアクセスする必要があり、技術要件を簡素化したいと考えています。この決定は、次のページに基づいています。

API キーは、コンソールを使用して生成する一意のキーです。アプリケーションがこのプロジェクトで有効になっている API を呼び出す必要がある場合、アプリケーションはこのキーをkey={API_key} パラメーターとしてすべての API 要求に渡します。このキーを使用する場合、ユーザーの操作や同意は必要なく、アカウント情報へのアクセスを許可することも、認証に使用することもありません。

Google Custom Search API など、ユーザー データを必要としない API のみを呼び出す場合は、API キーの方が実装が簡単な場合があります。ただし、アプリケーションがすでに OAuth 2.0 アクセス トークンを使用している場合は、API キーも生成する必要はありません。実際、OAuth 2.0 アクセス トークンが対応するプロジェクトにすでに関連付けられている場合、Google は渡された API キーを無視します。

API キーだけを使用した認証フローのコード例は多くありません。私が見つけたほとんどのものは、ダウンロードした .p12 ファイル ( GoogleCredentialjavadoc など) でクライアント ID を使用していることを示しています。私が見つけた 1 つのサンプル アプリケーションは、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 が必要ですか? そうだとすれば、Books Sample アプリで 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 なしで)?

4

2 に答える 2

3

vlatkoの答えは私を正しい軌道に乗せました。問題は、所有者のメール アドレスとサービス アカウントのメール アドレスを混同していたことが判明しました。たとえば、私は次のことを行っていました。

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();

また、owneremail@gmail.comAnalytics アプリケーションにユーザーとして追加しましたが、これも同様にサービス アカウントのメールアドレスである必要がありました。

于 2012-12-13T21:22:12.683 に答える
3

最初の質問に答えるには: 一般に、OAuth2.0 はユーザーのプライベート データへの承認済みアクセスに使用されるため、ユーザーの同意を得て、アクセス トークンを取得する必要があります。ただし、Google Books API の場合、パブリック データにアクセスする場合は、エンド ユーザーの同意は必要ないため、API キーで十分です。Books API を使用して非公開データにアクセスしようとする場合でも、OAuth2 トークンが必要になります。

あなたの場合の良いニュースは、OAuth2 を使用しても、アプリケーションが API にアクセスできると仮定して、ユーザーの関与をバイパスし、サービス アカウントを使用してフローを合理化できることです。ここで説明されているように、Analytics API 用にそれを設定する方法があります(サービス アカウント セクションの手順を確認してください)。ビルダーは正しい方向Credentialに進んでいると思いますが、ユーザーの偽装を行っていないため、そこにサービス アカウント ユーザーを設定する必要はないと思います。

于 2012-12-12T06:40:49.153 に答える