Übersicht
Zweck:In diesem Dokument wird erläutert, wie Sie die OAuth 2.0-Autorisierung mit Google-Diensten mithilfe der Dienstprogrammklasse GoogleCredential ausführen. 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:Verwenden Sie OAuth 2.0 für die Autorisierung, um auf geschützte Daten zuzugreifen, die in Google-Diensten gespeichert sind. Google APIs unterstützen OAuth 2.0-Abläufe für verschiedene Arten von Clientanwendungen. Bei all diesen Abläufen fordert die Clientanwendung ein Zugriffstoken an, das nur Ihrer Clientanwendung und dem Inhaber der geschützten Daten zugeordnet ist, auf die zugegriffen wird. Das Zugriffstoken ist auch mit einem begrenzten Bereich verknüpft, der die Art von Daten definiert, auf die Ihre Clientanwendung Zugriff hat (z. B. &Ihre Aufgaben verwalten"). Ein wichtiges Ziel für OAuth 2.0 ist es, einen sicheren und bequemen Zugriff auf die geschützten Daten zu ermöglichen und gleichzeitig die möglichen Auswirkungen zu minimieren, wenn ein Zugriffstoken gestohlen wird.
Die OAuth 2.0-Pakete in der Google API-Clientbibliothek für Java basieren auf der Google OAuth 2.0-Clientbibliothek für Java.
Weitere Informationen finden Sie in der Javadoc-Dokumentation für die folgenden Pakete:
- com.google.api.client.googleapis.auth.oauth2 (von google-api-client)
- com.google.api.client.googleapis.extensions.appengine.auth.oauth2 (von google-api-client-appengine)
Google API Console
Bevor Sie auf Google APIs zugreifen können, müssen Sie in der Google API Console ein Projekt für Authentifizierungs- und Abrechnungszwecke einrichten. Dies gilt unabhängig davon, ob es sich bei Ihrem Client um eine installierte Anwendung, eine mobile Anwendung, einen Webserver oder einen Client im Browser handelt.
Eine Anleitung zum ordnungsgemäßen Einrichten deiner Anmeldedaten findest du in der API Console-Hilfe.
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, können Sie so 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 der Google App Engine App Identity Java API. Im Gegensatz zu den Anmeldedaten, mit denen eine Clientanwendung Zugriff auf die Daten eines Endnutzers anfordert, bietet die App Identity API Zugriff auf die eigenen Daten der Clientanwendung.
Verwenden Sie AppIdentityCredential (aus google-api-client-appengine). Diese Anmeldedaten sind wesentlich einfacher, da Google App Engine alle Details übernimmt. Sie geben nur den erforderlichen OAuth 2.0-Bereich an.
Beispielcode aus 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
Ein Zugriffstoken läuft in der Regel nach 1 Stunde ab. Danach erhalten Sie eine Fehlermeldung, wenn Sie es verwenden möchten.
GoogleCredential aktualisiert das Token automatisch, d. h., es wird lediglich ein neues Zugriffstoken abgerufen. Dazu wird ein langlebiges Aktualisierungstoken verwendet, das normalerweise zusammen mit dem Zugriffstoken empfangen wird, wenn Sie den Parameter access_type=offline
während des Autorisierungscode-Ablaufs verwenden (siehe GoogleAutorisierungCodeFlow.Builder.setAccessType(String)).
Die meisten Anwendungen müssen das Zugriffstoken und/oder das Aktualisierungstoken beibehalten. Sie können Ihre eigene Implementierung von DataStoreFactory mit StoredCredential bereitstellen oder eine der folgenden Implementierungen der Bibliothek verwenden, um den Zugriffs- und/oder Aktualisierungstoken der Anmeldedaten beizubehalten.
- AppEngineDataStoreFactory: speichert die Anmeldedaten mithilfe der Google App Engine Data Store API
- MemoryDataStoreFactory: Anmeldedaten dauerhaft gespeichert
- FileDataStoreFactory: speichert die Anmeldedaten in einer Datei.
AppEngine-Nutzer: AppEngineCredentialStore wurde verworfen und wird bald entfernt. Wir empfehlen die Verwendung von AppEngineDataStoreFactory mit StoredCredential. Wenn Sie Anmeldedaten auf die alte Weise gespeichert haben, können Sie für die Migration die zusätzlichen Hilfsmethoden migrateTo(AppEngineDataStoreFactory) oder migrateTo(DataStore) verwenden.
Sie können DataStoreCredentialRefreshListener verwenden und ihn mit GoogleCredential.Builder.addRefreshListener(CredentialRefreshListener) für die Anmeldedaten festlegen.
Ablauf des Autorisierungscodes
Verwenden Sie den Autorisierungscode-Ablauf, damit der Endnutzer Ihrer Anwendung Zugriff auf seine geschützten Daten in Google APIs gewähren kann. Das Protokoll für diesen Vorgang wird in der Autorisierung von Codeberechtigungen beschrieben.
Dieser Ablauf wird mithilfe von GoogleAutorisierungCodeFlow implementiert. Folgende Schritte sind auszuführen:
- Der Endnutzer meldet sich in Ihrer Anwendung an. Sie müssen diesen Nutzer dann einer Nutzer-ID zuordnen, die für Ihre Anwendung eindeutig ist.
- Rufen Sie anhand der User-ID AutorisierungCodeFlow.loadCredential(String) auf, um zu prüfen, ob die Anmeldedaten des Endnutzers bereits bekannt sind. In diesem Fall sind wir fertig.
- Ist dies nicht der Fall, rufen Sie AutorisierungCodeFlow.newAutorisierungUrl() auf und leiten Sie den Browser des Endnutzers auf eine Autorisierungsseite weiter, um Ihrer Anwendung Zugriff auf ihre geschützten Daten zu gewähren.
- Der Google-Autorisierungsserver leitet den Browser dann zurück an die von Ihrer Anwendung angegebene Weiterleitungs-URL zusammen mit einem
code
-Abfrageparameter. Verwenden Sie den Parametercode
, um mit AutorisierungCodeFlow.newTokenRequest(String) ein Zugriffstoken anzufordern. - Verwenden Sie AutorisierungCodeFlow.createAndStoreCredential(TokenResponse, String)), um Anmeldedaten für den Zugriff auf geschützte Ressourcen zu speichern und abzurufen.
Wenn Sie GoogleAutorisierungCodeFlow nicht verwenden, können Sie auch die untergeordneten Klassen verwenden:
- Verwenden Sie DataStore.get(String), um die Anmeldedaten aus dem Store basierend auf der Nutzer-ID zu laden.
- Verwenden Sie GoogleAutorisierungCodeRequestUrl, um den Browser auf die Autorisierungsseite weiterzuleiten.
- Verwenden Sie AutorisierungCodeResponseUrl, um die Autorisierungsantwort zu verarbeiten und den Autorisierungscode zu parsen.
- Verwenden Sie GoogleAutorisierungCodeTokenRequest, um ein Zugriffstoken und möglicherweise ein Aktualisierungstoken anzufordern.
- Erstellen Sie ein neues GoogleCredential-Objekt und speichern Sie es mit DataStore.set(String, V).
- Greifen Sie über
GoogleCredential
auf geschützte Ressourcen zu. Abgelaufene Zugriffstokens werden automatisch mit dem Aktualisierungstoken aktualisiert (falls zutreffend). Achten Sie darauf, DataStoreCredentialRefreshListener zu verwenden und mit GoogleCredential.Builder.addRefreshListener(CredentialRefreshListener) als Anmeldedaten festzulegen.
Wenn Sie Ihr Projekt in der Google API Console einrichten, wählen Sie je nach verwendetem Ablauf verschiedene Anmeldedaten aus. Weitere Informationen finden Sie unter OAuth 2.0 einrichten und OAuth 2.0-Szenarien. Die Code-Snippets für die einzelnen Abläufe finden Sie unten.
Webserveranwendungen
Das Protokoll für diesen Vorgang wird im Abschnitt OAuth 2.0 für Webserveranwendungen verwenden erläutert.
Diese Bibliothek bietet Servlet-Hilfsklassen, die den Vorgang des Autorisierungscodes für grundlegende Anwendungsfälle erheblich vereinfachen. Sie stellen einfach konkrete Unterklassen von abstrakteAutorisierungCodeServlet und ZusammenfassungAutorisierungCodeCallbackServlet (von google-oauth-client-Servlet) bereit und fügen sie Ihrer web.xml-Datei hinzu. Sie müssen aber weiterhin die Nutzeranmeldung für Ihre Webanwendung vornehmen und eine User-ID extrahieren.
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-Ablauf in App Engine ist nahezu identisch mit dem Ablauf des Servlet-Autorisierungscodes. Der einzige Unterschied besteht darin, dass wir die Users Java API von Google App Engine nutzen können. Der Nutzer muss angemeldet sein, damit die Java-API für Nutzer aktiviert wird. Informationen zum Weiterleiten von Nutzern auf eine Anmeldeseite, sofern sie noch nicht angemeldet sind, finden Sie unter Sicherheit und Authentifizierung (in web.xml).
Der Hauptunterschied zum Aggregatorfall besteht darin, dass Sie konkrete Unterklassen von abstrakteAppEngineAutorisierungCodeServlet und abstrakteAppEngineAutorisierungCodeCallbackServlet (von google-oauth-client-appengine) bereitstellen.
Sie erweitern die abstrakten Servlet-Klassen und implementieren die Methode getUserId
mithilfe der Users Java API für Sie. AppEngineDataStoreFactory (von google-http-client-appengine) ist eine gute Option, um die Anmeldedaten mithilfe der Google App Engine Data Store API zu speichern.
Beispiel (leicht geändert) von 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 zusätzliches Beispiel finden Sie unter storage-serviceaccount-appengine-sample.
Dienstkonten
GoogleCredential unterstützt auch Dienstkonten. Im Gegensatz zu den Anmeldedaten, mit denen eine Clientanwendung Zugriff auf die Daten eines Endnutzers anfordert, bieten Dienstkonten Zugriff auf die eigenen Daten der Clientanwendung. Ihre Clientanwendung signiert die Anfrage für ein Zugriffstoken mithilfe eines privaten Schlüssels, der aus 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 zusätzliches Beispiel finden Sie unter storage-serviceaccount-cmdline-sample.
Identitätsdiebstahl
Sie können den Dienstkontofluss auch verwenden, um die Identität eines Nutzers in einer Domain anzunehmen, deren Inhaber Sie sind. Dieser Vorgang ist dem oben beschriebenen Dienstkonto sehr ähnlich, aber rufen Sie zusätzlich GoogleCredential.Builder.setServiceAccountUser(String) auf.
Installierte Apps
Dies ist der Befehlszeilen-Autorisierungscode, der unter OAuth 2.0 für installierte Anwendungen beschrieben wird.
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
Wenn Sie den browserbasierten Clientfluss verwenden möchten, der unter OAuth 2.0 für clientseitige Anwendungen beschrieben wird, gehen Sie normalerweise so vor:
- Leiten Sie den Endnutzer im Browser mithilfe von GoogleBrowserClientRequestUrl zur Autorisierungsseite weiter, um Ihrer Browseranwendung Zugriff auf die geschützten Daten des Endnutzers zu gewähren.
- Verwende die Google API-Clientbibliothek für JavaScript, um das Zugriffstoken im URL-Fragment beim Weiterleitungs-URI zu verarbeiten, der in der Google API Console registriert ist.
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
Welche Mediathek soll ich mit Android verwenden?
Wenn du die Entwicklung für Android entwickelst und die Google API, die du verwenden möchtest, in der Mediathek der Google Play-Dienste enthalten ist, solltest du diese Bibliothek verwenden, um die beste 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 Sie die Google API-Clientbibliothek für Java verwenden, die Android 4.0 (Ice Cream Sandwich) (oder höher) unterstützt und die hier beschrieben ist. Die Android-Unterstützung in der Google API-Clientbibliothek für Java ist @Beta.
Hintergrund:
Ab Eclair (SDK 2.1) werden Nutzerkonten auf dem Android-Gerät über den Account Manager verwaltet. Die gesamte Android-Anwendungsautorisierung wird zentral vom SDK mit AccountManager verwaltet. Sie geben den von Ihrer Anwendung benötigten OAuth 2.0-Bereich an und er gibt ein Zugriffstoken zurück.
Der OAuth 2.0-Bereich wird über den Parameter authTokenType
als oauth2:
und der Bereich angegeben. Beispiel:
oauth2:https://www.googleapis.com/auth/tasks
Gibt den Lese-/Schreibzugriff auf die Google Tasks API an. Wenn Sie mehrere OAuth 2.0-Umfänge benötigen, verwenden Sie eine durch Leerzeichen getrennte Liste.
Einige APIs haben spezielle authTokenType
-Parameter, die ebenfalls funktionieren. Beispielsweise ist „Manage your tasks“ ein Alias für das oben gezeigte Beispiel von authtokenType
.
Außerdem müssen Sie den API-Schlüssel in der Google API Console angeben. Andernfalls erhalten Sie vom Tokenmanager nur ein anonymes Kontingent, das normalerweise sehr niedrig ist. Wenn Sie dagegen einen API-Schlüssel angeben, erhalten Sie ein höheres kostenloses Kontingent. Außerdem können Sie optional die Abrechnung für die Nutzung darüber einrichten.
Beispiel für ein Code-Snippet aus task-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; } }