OAuth 2.0 mit der Google API-Clientbibliothek für Java verwenden

Übersicht

Zweck:In diesem Dokument wird die Verwendung des GoogleCredential Dienstprogrammklasse für die OAuth 2.0-Autorisierung für Google-Dienste. Für Informationen zu den von uns bereitgestellten generischen OAuth 2.0-Funktionen finden Sie unter OAuth 2.0 und die Google OAuth-Clientbibliothek für Java

Zusammenfassung:Wenn Sie auf geschützte Daten zugreifen möchten, die in Google-Diensten gespeichert sind, verwenden Sie OAuth 2.0 für die Autorisierung. Google APIs unterstützen OAuth 2.0-Abläufe für verschiedene Arten von Clientanwendungen. Bei all diesen Abläufen fordert die Client-Anwendung ein Zugriffstoken an, die nur mit Ihrer Clientanwendung und dem Eigentümer der geschützten Daten verknüpft sind, auf die zugegriffen wird. Das Zugriffstoken ist außerdem einem eingeschränkten Bereich zugeordnet, definiert die Art der Daten, auf die Ihre Clientanwendung zugreifen kann (z. B. „Aufgaben verwalten“). Ein wichtiges Ziel für OAuth 2.0 ist es, sichere und bequemen Zugriff auf die geschützten Daten zu ermöglichen und gleichzeitig die potenziellen Auswirkungen zu minimieren. wenn ein Zugriffstoken gestohlen wird.

Die OAuth 2.0-Pakete in der Google API-Clientbibliothek für Java basieren auf für allgemeine Zwecke Google OAuth 2.0-Clientbibliothek für Java

Weitere Informationen finden Sie in der Javadoc-Dokumentation für die folgenden Pakete:

Google API-Konsole

Bevor Sie auf Google APIs zugreifen können, müssen Sie ein Projekt auf der Google API Console für Authentifizierung und Abrechnung ob es sich bei Ihrem Client um eine installierte App, eine mobile App Webserver oder Client, der im Browser ausgeführt wird.

Eine Anleitung zum ordnungsgemäßen Einrichten Ihrer Anmeldedaten finden Sie auf der Hilfe zur API Console

Anmeldedaten

GoogleCredential

GoogleCredential ist eine threadsichere Hilfsklasse für OAuth 2.0 für den Zugriff auf geschützte Ressourcen mithilfe eines Zugriffstokens. Wenn Sie beispielsweise bereits ein Zugriffstoken haben, wie folgt eine Anfrage stellen:

GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken);
Plus plus = new Plus.builder(new NetHttpTransport(),
                             GsonFactory.getDefaultInstance(),
                             credential)
    .setApplicationName("Google-PlusSample/1.0")
    .build();

Google App Engine-Identität

Diese alternativen Anmeldedaten basieren auf dem Google App Engine App Identity Java API Im Gegensatz zu den Anmeldedaten, mit denen eine Client-Anwendung Zugriff auf einen Endnutzerdaten enthält, bietet die App Identity API Zugriff auf den Client Daten der Anwendung nutzen.

AppIdentityCredential verwenden (von google-api-client-appengine). Diese Anmeldedaten sind viel einfacher, da Google App Engine alle zu den Details. Sie geben nur den benötigten OAuth 2.0-Bereich an.

Beispielcode von urlshortener-robots-appengine-sample:

static Urlshortener newUrlshortener() {
  AppIdentityCredential credential =
      new AppIdentityCredential(
          Collections.singletonList(UrlshortenerScopes.URLSHORTENER));
  return new Urlshortener.Builder(new UrlFetchTransport(),
                                  GsonFactory.getDefaultInstance(),
                                  credential)
      .build();
}

Datenspeicher

Zugriffs-Tokens laufen in der Regel nach einer Stunde ab. Danach werden Sie erhalten Sie eine Fehlermeldung, wenn Sie versuchen, es zu verwenden. GoogleCredential sorgt dafür, dass die Seite das Token, was einfach bedeutet, ein neues Zugriffstoken. Dies erfolgt über ein langlebiges Aktualisierungstoken, das wird normalerweise zusammen mit dem Zugriffstoken empfangen, wenn Sie die Methode access_type=offline während des Autorisierungscode-Vorgangs (siehe GoogleAuthorizationCodeFlow.Builder.setAccessType(String) verwendet wird.

Die meisten Anwendungen müssen das Zugriffstoken der Anmeldedaten persistieren und/oder Aktualisierungstoken. Um das Zugriffs- und/oder Aktualisierungstoken der Anmeldedaten beizubehalten, können Sie Ihre eigene Implementierung von DataStoreFactory bereitstellen mit StoredCredential Alternativ können Sie eine der folgenden von der Bibliothek bereitgestellten Implementierungen verwenden:

  • AppEngineDataStoreFactory: die Anmeldedaten mithilfe der Google App Engine Data Store API beibehält
  • MemoryDataStoreFactory: "bleibt dauerhaft" die Anmeldedaten im Arbeitsspeicher, was nur als kurzfristige Speicherung für die Lebensdauer des Prozesses sinnvoll ist.
  • FileDataStoreFactory: und speichert die Anmeldedaten in einer Datei.

App Engine-Nutzer: AppEngineCredentialStore ist veraltet und wird bald entfernt. Wir empfehlen die Verwendung von AppEngineDataStoreFactory mit StoredCredential. Wenn Sie Anmeldedaten auf alte Weise gespeichert haben, können Sie die hinzugefügten Hilfsmethoden migrateTo(AppEngineDataStoreFactory) oder migrateTo(DataStore) um die Migration durchzuführen.

Sie können DataStoreCredentialRefreshListener und legen Sie ihn mithilfe von GoogleCredential.Builder.addRefreshListener(CredentialRefreshListener) als Berechtigungsnachweis fest.

Vorgang mit Autorisierungscode

Verwenden Sie den Vorgang mit Autorisierungscode, damit der Endnutzer Ihre Anwendung erteilen kann Zugriff auf ihre geschützten Daten in Google APIs zu erhalten. Das Protokoll für diesen Ablauf ist angegeben in Autorisierungscode gewähren

Dieser Ablauf wird mithilfe von GoogleAuthorizationCodeFlow implementiert. Folgende Schritte sind auszuführen:

Wenn Sie GoogleAuthorizationCodeFlow nicht verwenden, können Sie alternativ auch die niedrigeren Klassen nutzen:

Wenn Sie Ihr Projekt in der Google API Console einrichten, Sie können je nach verwendetem Ablauf verschiedene Anmeldedaten auswählen. Weitere Informationen finden Sie unter OAuth 2.0 einrichten. und OAuth 2.0-Szenarien. Code-Snippets für jeden der Abläufe finden Sie unten.

Webserveranwendungen

Das Protokoll für diesen Ablauf wird unter OAuth 2.0 für Webserveranwendungen verwenden.

Diese Bibliothek bietet Servlet-Hilfsklassen zur erheblichen Vereinfachung der Autorisierungscode-Vorgang für grundlegende Anwendungsfälle. Sie stellen einfach konkrete Unterklassen bereit, von AbstractAuthorizationCodeServlet und AbstractAuthorizationCodeCallbackServlet (von google-oauth-client-servlet) und fügen sie der Datei „web.xml“ hinzu. Sie müssen sich trotzdem noch um die melden Sie sich für Ihre Webanwendung an und extrahieren Sie eine Nutzer-ID.

public class CalendarServletSample extends AbstractAuthorizationCodeServlet {

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws IOException {
    // do stuff
  }

  @Override
  protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
    GenericUrl url = new GenericUrl(req.getRequestURL().toString());
    url.setRawPath("/oauth2callback");
    return url.build();
  }

  @Override
  protected AuthorizationCodeFlow initializeFlow() throws IOException {
    return new GoogleAuthorizationCodeFlow.Builder(
        new NetHttpTransport(), GsonFactory.getDefaultInstance(),
        "[[ENTER YOUR CLIENT ID]]", "[[ENTER YOUR CLIENT SECRET]]",
        Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(
        DATA_STORE_FACTORY).setAccessType("offline").build();
  }

  @Override
  protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
    // return user ID
  }
}

public class CalendarServletCallbackSample extends AbstractAuthorizationCodeCallbackServlet {

  @Override
  protected void onSuccess(HttpServletRequest req, HttpServletResponse resp, Credential credential)
      throws ServletException, IOException {
    resp.sendRedirect("/");
  }

  @Override
  protected void onError(
      HttpServletRequest req, HttpServletResponse resp, AuthorizationCodeResponseUrl errorResponse)
      throws ServletException, IOException {
    // handle error
  }

  @Override
  protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
    GenericUrl url = new GenericUrl(req.getRequestURL().toString());
    url.setRawPath("/oauth2callback");
    return url.build();
  }

  @Override
  protected AuthorizationCodeFlow initializeFlow() throws IOException {
    return new GoogleAuthorizationCodeFlow.Builder(
        new NetHttpTransport(), GsonFactory.getDefaultInstance()
        "[[ENTER YOUR CLIENT ID]]", "[[ENTER YOUR CLIENT SECRET]]",
        Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(
        DATA_STORE_FACTORY).setAccessType("offline").build();
  }

  @Override
  protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
    // return user ID
  }
}

Google App Engine-Anwendungen

Der Autorisierungscode-Vorgang in App Engine ist fast identisch mit dem Servlet. mit dem Autorisierungscode, außer dass wir die Users Java API Der Nutzer Sie müssen angemeldet sein, damit das Java-API für Nutzer aktiviert werden kann. finden Sie Informationen zu Weiterleitung von Nutzern zu einer Anmeldeseite, wenn diese nicht bereits angemeldet sind, siehe Sicherheit und Authentifizierung (in web.xml).

Der Hauptunterschied zum Servlet-Fall besteht darin, dass Sie konkrete abgeleiteten Klassen von AbstractAppEngineAuthorizationCodeServlet und AbstractAppEngineAuthorizationCodeCallbackServlet (von google-oauth-client-appengine. Sie erweitern die abstrakten Servlet-Klassen und implementieren die Methode getUserId. mit dem Java-API für Nutzer. AppEngineDataStoreFactory (von google-http-client-appengine) ist eine gute Option, um den Berechtigungsnachweis mithilfe der Google App Engine-Daten Store API

Leicht modifiziertes Beispiel aus calendar-appengine-sample:

public class CalendarAppEngineSample extends AbstractAppEngineAuthorizationCodeServlet {

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws IOException {
    // do stuff
  }

  @Override
  protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
    return Utils.getRedirectUri(req);
  }

  @Override
  protected AuthorizationCodeFlow initializeFlow() throws IOException {
    return Utils.newFlow();
  }
}

class Utils {
  static String getRedirectUri(HttpServletRequest req) {
    GenericUrl url = new GenericUrl(req.getRequestURL().toString());
    url.setRawPath("/oauth2callback");
    return url.build();
  }

  static GoogleAuthorizationCodeFlow newFlow() throws IOException {
    return new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY,
        getClientCredential(), Collections.singleton(CalendarScopes.CALENDAR)).setDataStoreFactory(
        DATA_STORE_FACTORY).setAccessType("offline").build();
  }
}

public class OAuth2Callback extends AbstractAppEngineAuthorizationCodeCallbackServlet {

  private static final long serialVersionUID = 1L;

  @Override
  protected void onSuccess(HttpServletRequest req, HttpServletResponse resp, Credential credential)
      throws ServletException, IOException {
    resp.sendRedirect("/");
  }

  @Override
  protected void onError(
      HttpServletRequest req, HttpServletResponse resp, AuthorizationCodeResponseUrl errorResponse)
      throws ServletException, IOException {
    String nickname = UserServiceFactory.getUserService().getCurrentUser().getNickname();
    resp.getWriter().print("<h3>" + nickname + ", why don't you want to play with me?</h1>");
    resp.setStatus(200);
    resp.addHeader("Content-Type", "text/html");
  }

  @Override
  protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
    return Utils.getRedirectUri(req);
  }

  @Override
  protected AuthorizationCodeFlow initializeFlow() throws IOException {
    return Utils.newFlow();
  }
}

Ein weiteres Beispiel finden Sie unter storage-serviceaccount-appengine-sample.

Dienstkonten

GoogleCredential unterstützt auch Dienstkonten. Im Gegensatz zu den Anmeldedaten, mit denen eine Client-Anwendung Zugriff auf einen Endnutzerdaten haben, ermöglichen Dienstkonten Zugriff auf die Ihre eigenen Daten. Ihre Clientanwendung signiert die Anfrage nach einem Zugriffstoken mithilfe von Einen privaten Schlüssel, der von der Google API Console heruntergeladen wurde

Beispielcode aus plus-serviceaccount-cmdline-sample:

HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory = GsonFactory.getDefaultInstance();
...
// Build service account credential.

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(PlusScopes.PLUS_ME));
// Set up global Plus instance.
plus = new Plus.Builder(httpTransport, jsonFactory, credential)
    .setApplicationName(APPLICATION_NAME).build();
...

Ein weiteres Beispiel finden Sie unter storage-serviceaccount-cmdline-sample.

Identitätsdiebstahl

Sie können den Dienstkontoablauf auch verwenden, um die Identität eines Nutzers in einer Domain zu übernehmen, die die Ihnen gehören. Dieser Ablauf ähnelt dem oben beschriebenen Dienstkontovorgang, Sie können jedoch Rufen Sie zusätzlich GoogleCredential.Builder.setServiceAccountUser(String) auf.

Installierte Apps

Dies ist der unter OAuth 2.0 für installierte Anwendungen beschriebene Ablauf mit Autorisierungscode.

Beispiel-Snippet aus plus-cmdline-sample:

public static void main(String[] args) {
  try {
    httpTransport = GoogleNetHttpTransport.newTrustedTransport();
    dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);
    // authorization
    Credential credential = authorize();
    // set up global Plus instance
    plus = new Plus.Builder(httpTransport, JSON_FACTORY, credential).setApplicationName(
        APPLICATION_NAME).build();
   // ...
}

private static Credential authorize() throws Exception {
  // load client secrets
  GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY,
      new InputStreamReader(PlusSample.class.getResourceAsStream("/client_secrets.json")));
  // set up authorization code flow
  GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
      httpTransport, JSON_FACTORY, clientSecrets,
      Collections.singleton(PlusScopes.PLUS_ME)).setDataStoreFactory(
      dataStoreFactory).build();
  // authorize
  return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
}

Clientseitige Anwendungen

So verwenden Sie den unter folgendem Link beschriebenen browserbasierten Clientfluss: OAuth 2.0 für clientseitige Anwendungen verwenden, gehen Sie in der Regel so vor:

  1. Endnutzer über den Browser auf die Autorisierungsseite weiterleiten GoogleBrowserClientRequestUrl um Ihrer Browseranwendung Zugriff auf die geschützten Daten des Endnutzers zu gewähren.
  2. Verwenden Sie die Google API-Clientbibliothek für JavaScript. um das Zugriffstoken zu verarbeiten, das im URL-Fragment unter der Weiterleitungs-URI gefunden wurde registriert in der Google API Console.

Verwendungsbeispiel für eine Webanwendung:

public void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException {
  String url = new GoogleBrowserClientRequestUrl("812741506391.apps.googleusercontent.com",
      "https://oauth2.example.com/oauthcallback", Arrays.asList(
          "https://www.googleapis.com/auth/userinfo.email",
          "https://www.googleapis.com/auth/userinfo.profile")).setState("/profile").build();
  response.sendRedirect(url);
}

Android

@Beta

Bibliothek für Android:

Wenn Sie für Android entwickeln und die gewünschte Google API enthalten ist in der Bibliothek der Google Play-Dienste, verwenden Sie diese Bibliothek, um eine optimale Leistung zu erzielen. Wenn die Google API, die Sie mit Android verwenden möchten, nicht Teil der Bibliothek der Google Play-Dienste ist, können die Google API-Clientbibliothek für Java verwenden, die Android 4.0 (Ice Cream Sandwich) unterstützt (oder höher) und der hier beschrieben wird. Die Unterstützung für Android in der Google Die API-Clientbibliothek für Java ist @Beta.

Hintergrund:

Ab Eclair (SDK 2.1) werden Nutzerkonten auf einem Android-Gerät verwaltet über den Account Manager. Die gesamte Android-Anwendungsautorisierung erfolgt zentral vom SDK verwaltet und verwendet, AccountManager Sie geben den OAuth 2.0-Bereich an, den Ihre Anwendung benötigt, und Sie erhalten einen Zugriff Token, das verwendet werden soll.

Der OAuth 2.0-Bereich wird über den Parameter authTokenType als oauth2: angegeben. und den Umfang. Beispiel:

oauth2:https://www.googleapis.com/auth/tasks

Legt den Lese-/Schreibzugriff auf die Google Tasks API fest. Wenn Sie mehrere OAuth 2.0-Bereiche, verwenden Sie eine durch Leerzeichen getrennte Liste.

Einige APIs haben spezielle authTokenType-Parameter, die ebenfalls funktionieren. Beispiel: „Aufgaben verwalten“ ist ein Alias für das oben gezeigte authtokenType-Beispiel.

Sie müssen auch den API-Schlüssel aus der Google API Console: Andernfalls stellt das Token, das Sie vom AccountManager erhalten, nur anonymes Kontingent, das normalerweise sehr niedrig ist. Wenn Sie dagegen eine API erhalten Sie ein höheres kostenloses Kontingent und können optional die Abrechnung für die Nutzung einrichten. darüber stehen.

Beispiel-Code-Snippet aus tasks-android-sample:

com.google.api.services.tasks.Tasks service;

@Override
public void onCreate(Bundle savedInstanceState) {
  credential =
      GoogleAccountCredential.usingOAuth2(this, Collections.singleton(TasksScopes.TASKS));
  SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
  credential.setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, null));
  service =
      new com.google.api.services.tasks.Tasks.Builder(httpTransport, jsonFactory, credential)
          .setApplicationName("Google-TasksAndroidSample/1.0").build();
}

private void chooseAccount() {
  startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  switch (requestCode) {
    case REQUEST_GOOGLE_PLAY_SERVICES:
      if (resultCode == Activity.RESULT_OK) {
        haveGooglePlayServices();
      } else {
        checkGooglePlayServicesAvailable();
      }
      break;
    case REQUEST_AUTHORIZATION:
      if (resultCode == Activity.RESULT_OK) {
        AsyncLoadTasks.run(this);
      } else {
        chooseAccount();
      }
      break;
    case REQUEST_ACCOUNT_PICKER:
      if (resultCode == Activity.RESULT_OK && data != null && data.getExtras() != null) {
        String accountName = data.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME);
        if (accountName != null) {
          credential.setSelectedAccountName(accountName);
          SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
          SharedPreferences.Editor editor = settings.edit();
          editor.putString(PREF_ACCOUNT_NAME, accountName);
          editor.commit();
          AsyncLoadTasks.run(this);
        }
      }
      break;
  }
}