Übersicht
Zweck:In diesem Dokument werden die generischen OAuth 2.0-Funktionen von der Google OAuth-Clientbibliothek für Java Sie können diese Funktionen für Authentifizierung und Autorisierung für Internetdienste.
Eine Anleitung zur Verwendung von GoogleCredential
für die OAuth 2.0-Autorisierung mit
Google-Diensten finden Sie unter
OAuth 2.0 mit der Google API-Clientbibliothek für Java verwenden
Zusammenfassung: OAuth 2.0 ist ein Standardspezifikation, die es Endnutzern ermöglicht, einen Client sicher zu autorisieren um auf geschützte serverseitige Ressourcen zuzugreifen. Darüber hinaus enthält der OAuth 2.0-Inhabertoken wird erläutert, wie der Zugriff auf diese geschützten Ressourcen Token, das während der Endnutzerautorisierung gewährt wurde.
Weitere Informationen finden Sie in der Javadoc-Dokumentation für die folgenden Pakete:
- com.google.api.client.auth.oauth2 (von google-oauth-client)
- com.google.api.client.extensions.servlet.auth.oauth2 (from google-oauth-client-servlet)
- com.google.api.client.extensions.appengine.auth.oauth2 (from google-oauth-client-appengine)
Kundenregistrierung
Bevor Sie die Google OAuth-Clientbibliothek für Java verwenden, müssen Sie Ihre Anwendung bei einem Autorisierungsserver registrieren, um eine Client-ID und Clientschlüssel. (Allgemeine Informationen zu diesem Vorgang finden Sie in der Kunde Registrierungsspezifikation.
Anmeldedaten- und Anmeldedatenspeicher
Qualifikation
ist eine Thread-sichere OAuth 2.0-Hilfsklasse für den Zugriff auf geschützte Ressourcen mithilfe eines
ein Zugriffstoken hinzufügen. Bei Verwendung eines Aktualisierungstokens aktualisiert Credential
auch den Zugriff
Token, wenn das Zugriffstoken abläuft, verwenden Sie dazu das Aktualisierungstoken. Wenn Sie beispielsweise
bereits über ein Zugriffstoken verfügt, können Sie so eine Anfrage stellen:
public static HttpResponse executeGet( HttpTransport transport, JsonFactory jsonFactory, String accessToken, GenericUrl url) throws IOException { Credential credential = new Credential(BearerToken.authorizationHeaderAccessMethod()).setAccessToken(accessToken); HttpRequestFactory requestFactory = transport.createRequestFactory(credential); return requestFactory.buildGetRequest(url).execute(); }
Die meisten Anwendungen müssen das Zugriffs-Token der Anmeldedaten Aktualisierungs-Token, um eine künftige Weiterleitung zur Autorisierung zu vermeiden Seite im Browser. Die CredentialStore -Implementierung in dieser Bibliothek wurde verworfen und wird in Zukunft entfernt Veröffentlichungen. Alternativ können Sie die Methode DataStoreFactory und DataStore Benutzeroberflächen mit StoredCredential die vom Google HTTP-Clientbibliothek für Java
Sie können eine der folgenden von der Bibliothek bereitgestellten Implementierungen verwenden:
- JdoDataStoreFactory die Anmeldedaten mithilfe von JDO beibehält.
- AppEngineDataStoreFactory die Anmeldedaten mithilfe der Google App Engine Data Store API beibehält
- MemoryDataStoreFactory "bleibt dauerhaft" die Anmeldedaten im Arbeitsspeicher, was nur als kurzfristige Speicherplatz für die Lebensdauer des Prozesses.
- FileDataStoreFactory und speichert die Anmeldedaten in einer Datei.
Google App Engine-Nutzer:
AppEngineCredentialStore wurde verworfen und wird entfernt.
Wir empfehlen die Verwendung von AppEngineDataStoreFactory mit StoredCredential. Wenn Sie Anmeldedaten auf die alte Weise gespeichert haben, können Sie die zusätzlichen Hilfsmethoden verwenden. migrateTo(AppEngineDataStoreFactory) oder migrateTo(DataStore) zu migrieren.
DataStoreCredentialRefreshListener verwenden und legen Sie ihn für die Anmeldedaten GoogleCredential.Builder.addRefreshListener(CredentialRefreshListener).
Vorgang mit Autorisierungscode
Verwenden Sie den Vorgang mit Autorisierungscode, damit der Endnutzer Ihre Anwendung erteilen kann Zugriff auf ihre geschützten Daten haben. Das Protokoll für diesen Ablauf wird in der Spezifikation der Autorisierungscode-Erteilung
Dieser Ablauf wird mithilfe von AuthorizationCodeFlow. Folgende Schritte sind auszuführen:
- Ein Endnutzer meldet sich bei Ihrer Anwendung an. Sie müssen diesen Nutzer mit Eine Nutzer-ID, die für Ihre Anwendung eindeutig ist.
- Anruf AuthorizationCodeFlow.loadCredential(String), basierend auf der Nutzer-ID, um zu prüfen, ob die Anmeldedaten des Nutzers bereits bekannt sind. Wenn ja, brauchen Sie nichts weiter zu tun.
- Falls nicht, rufen Sie AuthorizationCodeFlow.newAuthorizationUrl() auf. und den Browser des Endnutzers auf eine Autorisierungsseite weiterleiten, auf der er Zugriff auf ihre geschützten Daten zu haben.
- Der Webbrowser leitet den Nutzer dann mit einem „Code“ an die Weiterleitungs-URL weiter. Suchanfrage Parameter, der dann verwendet werden kann, um ein Zugriffstoken mithilfe AuthorizationCodeFlow.newTokenRequest(String) verwenden.
- Verwenden Sie AuthorizationCodeFlow.createAndStoreCredential(TokenResponse, String) Anmeldedaten für den Zugriff auf geschützte Ressourcen zu speichern und abzurufen.
Wenn Sie nicht die AuthorizationCodeFlow können Sie die untergeordneten Klassen verwenden:
- Verwenden Sie DataStore.get(String). um die Anmeldedaten basierend auf der Nutzer-ID aus dem Speicher zu laden.
- Verwenden Sie AuthorizationCodeRequestUrl. um den Browser auf die Autorisierungsseite weiterzuleiten.
- Verwenden Sie AuthorizationCodeResponseUrl. um die Autorisierungsantwort zu verarbeiten und den Autorisierungscode zu parsen.
- Verwenden Sie AuthorizationCodeTokenRequest. um ein Zugriffstoken und eventuell ein Aktualisierungstoken anzufordern.
- Erstellen Sie ein neues Credential und speichern Sie es mithilfe von DataStore.set(String, V).
- Greifen Sie mit den Anmeldedaten auf geschützte Ressourcen zu. Abgelaufene Zugriffstokens werden automatisch mit dem Aktualisierungstoken aktualisiert, wenn zutreffend sind. Achten Sie darauf, DataStoreCredentialRefreshListener und legen Sie ihn für die Anmeldedaten Credential.Builder.addRefreshListener(CredentialRefreshListener).
Vorgang mit Servlet-Autorisierungscode
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.
Beispielcode:
public class ServletSample 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 AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(), new NetHttpTransport(), new JacksonFactory(), new GenericUrl("https://server.example.com/token"), new BasicAuthentication("s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw"), "s6BhdRkqt3", "https://server.example.com/authorize").setCredentialDataStore( StoredCredential.getDefaultDataStore( new FileDataStoreFactory(new File("datastoredir")))) .build(); } @Override protected String getUserId(HttpServletRequest req) throws ServletException, IOException { // return user ID } } public class ServletCallbackSample 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 AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(), new NetHttpTransport(), new JacksonFactory(), new GenericUrl("https://server.example.com/token"), new BasicAuthentication("s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw"), "s6BhdRkqt3", "https://server.example.com/authorize").setCredentialDataStore( StoredCredential.getDefaultDataStore( new FileDataStoreFactory(new File("datastoredir")))) .build(); } @Override protected String getUserId(HttpServletRequest req) throws ServletException, IOException { // return user ID } }
Google App Engine-Vorgang mit Autorisierungscode
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 muss angemeldet sein, damit das Java-API für Nutzer aktiviert werden kann. für Informationen zur Weiterleitung von Nutzern auf eine Anmeldeseite, sofern diese 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 getUserId
-Methode mithilfe der Users Java API für Sie. AppEngineDataStoreFactory (aus der Google HTTP-Clientbibliothek für Java) ist eine gute Option, um die Anmeldedaten mithilfe der Google App Engine Data Store API dauerhaft zu speichern.
Beispielcode:
public class AppEngineSample extends AbstractAppEngineAuthorizationCodeServlet { @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 AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(), new UrlFetchTransport(), new JacksonFactory(), new GenericUrl("https://server.example.com/token"), new BasicAuthentication("s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw"), "s6BhdRkqt3", "https://server.example.com/authorize").setCredentialStore( StoredCredential.getDefaultDataStore(AppEngineDataStoreFactory.getDefaultInstance())) .build(); } } public class AppEngineCallbackSample extends AbstractAppEngineAuthorizationCodeCallbackServlet { @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 AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(), new UrlFetchTransport(), new JacksonFactory(), new GenericUrl("https://server.example.com/token"), new BasicAuthentication("s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw"), "s6BhdRkqt3", "https://server.example.com/authorize").setCredentialStore( StoredCredential.getDefaultDataStore(AppEngineDataStoreFactory.getDefaultInstance())) .build(); } }
Autorisierungscode-Vorgang für die Befehlszeile
Vereinfachter Beispielcode von dailymotion-cmdline-sample:
/** Authorizes the installed application to access user's protected data. */ private static Credential authorize() throws Exception { OAuth2ClientCredentials.errorIfNotSpecified(); // set up authorization code flow AuthorizationCodeFlow flow = new AuthorizationCodeFlow.Builder(BearerToken .authorizationHeaderAccessMethod(), HTTP_TRANSPORT, JSON_FACTORY, new GenericUrl(TOKEN_SERVER_URL), new ClientParametersAuthentication( OAuth2ClientCredentials.API_KEY, OAuth2ClientCredentials.API_SECRET), OAuth2ClientCredentials.API_KEY, AUTHORIZATION_SERVER_URL).setScopes(Arrays.asList(SCOPE)) .setDataStoreFactory(DATA_STORE_FACTORY).build(); // authorize LocalServerReceiver receiver = new LocalServerReceiver.Builder().setHost( OAuth2ClientCredentials.DOMAIN).setPort(OAuth2ClientCredentials.PORT).build(); return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user"); } private static void run(HttpRequestFactory requestFactory) throws IOException { DailyMotionUrl url = new DailyMotionUrl("https://api.dailymotion.com/videos/favorites"); url.setFields("id,tags,title,url"); HttpRequest request = requestFactory.buildGetRequest(url); VideoFeed videoFeed = request.execute().parseAs(VideoFeed.class); ... } public static void main(String[] args) { ... DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR); final Credential credential = authorize(); HttpRequestFactory requestFactory = HTTP_TRANSPORT.createRequestFactory(new HttpRequestInitializer() { @Override public void initialize(HttpRequest request) throws IOException { credential.initialize(request); request.setParser(new JsonObjectParser(JSON_FACTORY)); } }); run(requestFactory); ... }
Browserbasierter Clientfluss
Dies sind die typischen Schritte des browserbasierten Clientflusses, der in der Implicit Grant-Spezifikation:
- Verwenden Sie BrowserClientRequestUrl, den Browser des Endnutzers auf die Autorisierungsseite weiterleiten, Ihrer Anwendung Zugriff auf ihre geschützten Daten zu gewähren.
- Verwenden Sie eine JavaScript-Anwendung, um das in der URL gefundene Zugriffstoken zu verarbeiten. Fragment beim Weiterleitungs-URI, der beim Autorisierungsserver registriert ist.
Verwendungsbeispiel für eine Webanwendung:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { String url = new BrowserClientRequestUrl( "https://server.example.com/authorize", "s6BhdRkqt3").setState("xyz") .setRedirectUri("https://client.example.com/cb").build(); response.sendRedirect(url); }
Abgelaufenes Zugriffstoken erkennen
Gemäß der OAuth 2.0-Inhaberspezifikation
Der Server wird aufgerufen, um auf eine geschützte Ressource mit einem abgelaufenen Zugriff zuzugreifen.
-Token, antwortet der Server normalerweise mit dem HTTP-Statuscode 401 Unauthorized
wie zum Beispiel:
HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer realm="example", error="invalid_token", error_description="The access token expired"
Die Spezifikation scheint jedoch sehr flexibel zu sein. Für finden Sie in der Dokumentation des OAuth 2.0-Anbieters.
Alternativ können Sie den Parameter expires_in
im
Zugriffstoken-Antwort.
Gibt die Lebensdauer des gewährten Zugriffstokens in Sekunden an:
in der Regel eine Stunde. Das Zugriffstoken läuft jedoch möglicherweise nicht am Ende ab.
und der Server lässt den Zugriff
möglicherweise weiterhin zu. Aus diesem Grund
empfehlen in der Regel, auf den Statuscode 401 Unauthorized
zu warten, anstatt
davon aus, dass das Token basierend auf der verstrichenen Zeit abgelaufen ist. Alternativ können Sie
versuchen, ein Zugriffstoken kurz vor Ablauf zu aktualisieren, und wenn der Tokenserver
nicht verfügbar ist, verwenden Sie das Zugriffstoken so lange, bis Sie eine 401
erhalten. Dieses
ist die Strategie, die standardmäßig in
Anmeldedaten:
Eine weitere Möglichkeit besteht darin, vor jeder Anfrage ein neues Zugriffstoken zu erhalten, erfordert jedes Mal eine zusätzliche HTTP-Anforderung an den Tokenserver. Es handelt sich daher wahrscheinlich schlechte Wahl in Bezug auf Geschwindigkeit und Netzwerknutzung. Idealerweise sollten Sie das Zugriffstoken in einem sicheren, nichtflüchtigen Speicher, um die Anfragen einer Anwendung nach neuem Zugriff zu minimieren Tokens. Bei installierten Anwendungen stellt der sichere Speicher jedoch eine Herausforderung dar.
Beachten Sie, dass ein Zugriffstoken aus anderen Gründen ungültig werden kann, wenn der Nutzer das Token explizit widerrufen hat, achten Sie also darauf, dass Ihr Fehlerbehandlungscode zuverlässig ist. Wenn Sie feststellen, dass ein Token nicht mehr gültig ist, wenn er beispielsweise abgelaufen ist oder widerrufen wurde, müssen Sie den Zugriff aus Ihrem Speicher. Auf Android-Geräten müssen Sie zum Beispiel AccountManager.invalidateAuthToken auf.