19

まず、これは 2 つの部分からなる質問なので、私がやろうとしていることを説明させてください。

Googleカレンダーにアクセスして操作できるように、OAuth2を介してGoogleアカウントで内部認証するJAX-RSサービスを構築しています。このサービスは Web サイト (Joomla) によって呼び出され、サイトにログインしたユーザーはカレンダー イベントに電子メール アドレスを登録できるため、イベントが近づいたときに電子メール通知を受け取ることができます。これらのユーザーは、基になる Google アカウントについて何も知りません。

私の最初の質問は、サービス アカウント認証を使用することは正しいことですか? Google ドキュメントを見ると、人間以外の認証 (つまり、サーバー間認証) に対応する唯一のユース ケースです。

2 つ目の問題は、これを行うコードを書いたのですが、カレンダー フィードの execute メソッドを呼び出すと、401/Unauthorized 応答が返され、次のエラーが返されることです。このコードは、Google のサンプルから削除されました。

Google Calendar API の v3-rev3-1.5.0-beta を使用しています。アカウントで Calendar API を有効にし、以下のコードで使用される秘密鍵を作成してダウンロードしました。

Web サーバーからではなく、Eclipse で以下のコードをローカルで呼び出しています。

したがって、最初に行う呼び出しは、資格情報オブジェクトを取得することです (ID は X で難読化されています)。

private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
.
.
.
GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
            .setJsonFactory(JSON_FACTORY)
            .setServiceAccountId("284XXXXXXXX@developer.gserviceaccount.com")
            .setServiceAccountScopes(CalendarScopes.CALENDAR)
            .setServiceAccountPrivateKeyFromP12File(new File("D:/3cd8XXXXXXXXXXXXXXXXXXXXXXXXXXXXXd635e-privatekey.p12"))
            .build();

次のステップは、次のように Calendar API を呼び出すことです (その間に他のコードは呼び出されません)。

 Calendar calendar = Calendar.builder(HTTP_TRANSPORT, JSON_FACTORY)
        .setApplicationName("TestApp-Calendar/1.0").setHttpRequestInitializer(credential)
        .build();

 CalendarList feed = calendar.calendarList().list().execute();

list().execute() を呼び出すと、次のエラーが発生します。

com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized { "code": 401, "errors": [ { "domain": "global", "location": "Authorization", "locationType": " header", "message" : "ログインが必要です", "reason" : "required" } ], "message" : "Login Required" } at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException. java:159) com.google.api.client.googleapis.json.GoogleJsonResponseException.execute(GoogleJsonResponseException.java:187) で com.google.api.client.googleapis.services.GoogleClient.executeUnparsed(GoogleClient.java:115) でcom.google.api.client.http.json で。uk.org.reigatepriorybowmen.Service.registerEmailForAllCalendarEvents(Service.java: 55) uk.org.reigatepriorybowmen.Service.main(Service.java:74) で

サービス アカウントは次のように設定されます。

ここに画像の説明を入力

それで、私は何を間違っていますか?私は何時間もグーグルで解決策を探してきたので、これが私の最後の希望です.

ご協力いただきありがとうございます。

ジャスティン

4

6 に答える 6

6

401 に関しては、Google の API がおかしいようです。しばらくして初めてア​​プリを実行すると、一見ランダムな間隔で時間間隔が広がり、常に 401 が返されます。2 回目または 3 回目のラウンドで、実際にログインします。

この動作は、こちらの Google の Task API サンプル コードでも説明されています。

次のコードに注意してください。

void onRequestCompleted() {
received401 = false;
}

void handleGoogleException(IOException e) {
if (e instanceof GoogleJsonResponseException) {
  GoogleJsonResponseException exception = (GoogleJsonResponseException) e;
  if (exception.getStatusCode() == 401 && !received401) {
    received401 = true;
    accountManager.invalidateAuthToken(credential.getAccessToken());
    credential.setAccessToken(null);
    SharedPreferences.Editor editor2 = settings.edit();
    editor2.remove(PREF_AUTH_TOKEN);
    editor2.commit();
    gotAccount();
    return;
  }
}
Log.e(TAG, e.getMessage(), e);

}

Google 自身のコード サンプルでは、​​初めて 401 を規定しました。これは、コードで処理する必要がある特別なセキュリティ問題である可能性があります。

于 2012-08-07T05:41:36.523 に答える
1

偽装しようとしているユーザーを指定する必要があると思います。

現在 ServiceAccount を使用している方法は、アプリケーションまたはサービス アカウント自体に関連するデータにアクセスする場合にのみ有効です。Google カレンダーのデータにアクセスするには、ドメイン ユーザーのデータにアクセスする権限を持つ Google Apps ドメイン管理者である必要があります。間違っている場合はお知らせください。Google カレンダーのデータはユーザーに属しているため、偽装しようとしているユーザーを指定する必要があります。

Javaを使用してこれを行うには、 GoogleCredential.Builder#setServiceAccountUser(String)を使用する必要があるようです

してみてください:

GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
        .setJsonFactory(JSON_FACTORY)
        .setServiceAccountId("284XXXXXXXX@developer.gserviceaccount.com")
        .setServiceAccountScopes(CalendarScopes.CALENDAR)
        .setServiceAccountPrivateKeyFromP12File(new File("/path/to/privatekey.p12"))
        .setServiceAccountUser("user@domain.com")
        .build();

また、API プロジェクトで (API コンソールから) サービス アカウント キーを作成したら、このプロジェクトを cPanel の承認済みサード パーティ アプリのリストに追加する必要があります。詳細については、こちらを参照してください。使用する必要がある「クライアント ID」は、サービス アカウント キーにバインドされたもので、次のようになります。<APP_ID>-<OTHER_KEY>.apps.googleusercontent.com

于 2012-05-05T00:32:32.310 に答える
1

このような動作は、管理パネル (あなたの場合はドキュメント パネルだと思います) に API ユーザーを追加しなかった場合に発生する可能性があります。秘密鍵を作成した後の Google API サービス アカウント)。アナリティクスでは、次のようになります。

Google アナリティクスの例

于 2012-06-27T22:16:57.613 に答える
1

私は Android モバイル アプリの開発者です。Google カレンダー API (OAuth 2.0) を使用してアプリケーションを作成しています。私もこの同じエラーに直面しました。しかし、今、私はエラーを解決しました。シナリオとその解決策を書いています。
特定のカレンダーのカレンダー イベントを取得する URL (モバイル アプリ API):

https://www.googleapis.com/calendar/v3/calendars/en.indian%23holiday%40group.v.calendar.google.com/events?access_token=ya29.AHES6ZQyP3iDZM8PF-7ZqZE8oKmWAgUX55sPGPTjGbM5A

この URL では、calendarId を追加する必要があります。URL の形式は次のとおりです。

https://www.googleapis.com/calendar/v3/calendars/<calendarId>/events

URLに追加する前にcalendarIdをエンコードしていませんでした。calendarId をエンコードしてから、Http リクエストを作成しました。その後、すべてがうまくいきました。

final String accessToken=dataStore.getAccessToken();

    List<NameValuePair> params = new LinkedList<NameValuePair>();
    params.add(new BasicNameValuePair("access_token", accessToken));
    String paramString = URLEncodedUtils.format(params, "utf-8");

    final String url = String.format(AuthConstants.CALENDAR_EVENTS_URI,URLEncoder.encode(calendarId))+"?"+ paramString;

これで、カレンダー イベントが JSON で返されます。

于 2013-02-15T11:14:17.417 に答える
0

OK、それで私はこれで遊んでいて、401エラーを乗り越えました、しかし私は今403を打っています。しかし、私は少なくとも401問題に答える私が書いたコードを詳述します。

サービスアカウントの設定を変更したり、キーなどを再生成したりしませんでした。これはすべて同じです。

変更点はコードの一部であり、CalendarAPIのv3r20lv1.12.0-betaにアップグレードしました。

以下のコードは、上記のOPで詳しく説明されているように、同じままです。

private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
.
.
.
GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
        .setJsonFactory(JSON_FACTORY)
        .setServiceAccountId("284XXXXXXXX@developer.gserviceaccount.com")
        .setServiceAccountScopes(CalendarScopes.CALENDAR)
        .setServiceAccountPrivateKeyFromP12File(new File("D:/3cd8XXXXXXXXXXXXXXXXXXXXXXXXXXXXXd635e-privatekey.p12"))
        .build();

カレンダーのハンドルを取得するコードが変更されましたが、これはAPIの変更によって強制されました。

Calendar calendar = new Calendar(HTTP_TRANSPORT, JSON_FACTORY, credential);

この時点で、次のコードを実行することで、カレンダーを繰り返し処理してイベントを確認できます(これによりイベントの概要が出力されます)。

Events events = calendar.events().list(CALENDAR_ID).execute();

for (Event event : events.getItems())
{
    System.out.println(event.getSummary());
}

しかし、イベントを更新しようとすると、403Forbiddenエラーが発生します。このために別のスレッドを作成し、2つのスレッドをリンクします。

助けてくれてありがとう!

編集:これが新しいスレッドです。

于 2012-12-22T13:05:19.277 に答える