Omówienie
Cel: ten dokument wyjaśnia, jak korzystać z GoogleCredential klasy narzędzia do autoryzacji OAuth 2.0 za pomocą usług Google. Dla: informacji na temat funkcji OAuth 2.0, które udostępniamy, Protokół OAuth 2.0 i biblioteka klienta Google OAuth dla języka Java
Podsumowanie: aby uzyskać dostęp do danych chronionych przechowywanych w usługach Google, użyj OAuth 2.0 do autoryzacji. Interfejsy API Google obsługują przepływy OAuth 2.0 dla różnych typów aplikacji klienckich. We wszystkich tych przepływach aplikacja kliencka wysyła żądanie tokena dostępu, który jest powiązane wyłącznie z Twoją aplikacją kliencką i właścicielem chronionych danych na dostęp do danych. Token dostępu jest też powiązany z ograniczonym zakresem, który określa rodzaj danych, do których aplikacja kliencka ma dostęp (na przykład „Zarządzaj zadaniami”). Ważnym celem protokołu OAuth 2.0 jest zapewnienie wygodny dostęp do chronionych danych przy minimalizacji potencjalnego wpływu w przypadku kradzieży tokena dostępu.
Pakiety OAuth 2.0 w bibliotece klienta interfejsów API Google dla języka Java są oparte na do zwykłych obciążeń Biblioteka klienta Google OAuth 2.0 dla języka Java.
Szczegółowe informacje znajdziesz w dokumentacji Javadoc dotyczącej tych pakietów:
- com.google.api.client.googleapis.auth.oauth2 (z google-api-client)
- com.google.api.client.googleapis.extensions.appengine.auth.oauth2 (z google-api-client-appengine)
Konsola interfejsów API Google
Aby uzyskać dostęp do interfejsów API Google, musisz skonfigurować projekt w Konsola interfejsów API Google do uwierzytelniania i rozliczeń niezależnie od tego, czy jest to aplikacja zainstalowana, mobilna, serwer WWW lub klient działający w przeglądarce.
Instrukcje poprawnego konfigurowania danych logowania znajdziesz w Pomoc dotycząca konsoli API.
Dane logowania
GoogleCredential
GoogleCredential to klasa pomocnicza oparta na wątkach, która umożliwia dostęp do chronionych zasobów przez OAuth 2.0 za pomocą tokena dostępu. Jeśli na przykład masz już token dostępu, może przesłać żądanie w następujący sposób:
GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken); Plus plus = new Plus.builder(new NetHttpTransport(), GsonFactory.getDefaultInstance(), credential) .setApplicationName("Google-PlusSample/1.0") .build();
Tożsamość Google App Engine
Te alternatywne dane logowania opierają się na Interfejs Google App Engine App Identity Java API. W przeciwieństwie do danych logowania, dla których aplikacja kliencka prosi o dostęp do do danych użytkownika, interfejs App Identity API zapewnia dostęp do klienta z własnymi danymi aplikacji.
Użyj AppIdentityCredential. (z google-api-client-appengine). Te dane logowania są znacznie prostsze, ponieważ Google App Engine obsługuje wszystkie szczegóły. Określasz tylko potrzebny zakres protokołu OAuth 2.0.
Przykładowy kod pobrany ze strony 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(); }
Magazyn danych
Token dostępu ma zwykle datę ważności po upływie 1 godziny. Po tym czasie
pojawi się błąd, jeśli spróbujesz go użyć.
GoogleCredential
dba o automatyczne „odświeżanie” czyli po prostu
nowy token dostępu. Służy do tego długotrwały token odświeżania,
jest zwykle odbierany razem z tokenem dostępu, jeśli używasz
access_type=offline
podczas przepływu kodu autoryzacji (patrz
GoogleAuthorizationCodeFlow.Builder.setAccessType(String)).
Większość aplikacji musi zachować token dostępu danych logowania lub token odświeżania. Aby zachować dostęp do danych logowania lub tokeny odświeżania danych logowania, możesz własną implementację DataStoreFactory. za pomocą StoredCredential; Możesz też skorzystać z jednej z poniższych implementacji udostępnianych przez bibliotekę:
- AppEngineDataStoreFactory: nadal zachowuje dane logowania przy użyciu interfejsu Google App Engine Data Store API.
- MemoryDataStoreFactory: „utrwala” dane uwierzytelniające w pamięci, które są przydatne tylko jako krótkoterminowa pamięć masowa całego procesu.
- FileDataStoreFactory: zachowa dane logowania w pliku.
Użytkownicy App Engine: AppEngineCredentialStore jest wycofany i wkrótce zostanie usunięty. Zalecamy użycie ciągu AppEngineDataStoreFactory za pomocą danych StoredCredential. Jeśli masz dane uwierzytelniające zapisane w starym stylu, możesz użyć dodanego metody pomocnicze migrateTo(AppEngineDataStoreFactory) lub migrateTo(DataStore) aby przeprowadzić migrację.
Możesz użyć DataStoreCredentialRefreshListener i ustaw go dla danych logowania za pomocą GoogleCredential.Builder.addRefreshListener(CredentialRefreshListener)).
Przepływ kodu autoryzacji
Użyj przepływu kodu autoryzacji, aby zezwolić użytkownikowi na przyznanie Twojej aplikacji dostępu do ich chronionych danych w interfejsach API Google. Protokół tego procesu to określona w Authorization Code Grant (Przyznanie kodu autoryzacji).
Implementacja tego procesu odbywa się za pomocą GoogleAuthorizationCodeFlow. Kroki:
- Użytkownik loguje się do Twojej aplikacji. Konieczne będzie powiązanie tego użytkownika unikalnym identyfikatorem użytkownika dla Twojej aplikacji.
- Wywołaj AuthorizationCodeFlow.loadCredential(String)). na podstawie identyfikatora użytkownika, aby sprawdzić, czy dane logowania użytkownika są już znane. Jeśli tak, to już koniec.
- Jeśli nie, wywołaj AuthorizationCodeFlow.newAuthorizationUrl(). i przekierować przeglądarkę użytkownika na stronę autoryzacji, która pozwala dostępu aplikacji do ich chronionych danych.
- Serwer autoryzacji Google przekieruje wtedy przeglądarkę z powrotem do
adres URL przekierowania określony przez aplikację, wraz z zapytaniem
code
. Użyj parametrucode
, aby poprosić o token dostępu za pomocą AuthorizationCodeFlow.newTokenRequest(String)). - Użyj AuthorizationCodeFlow.createAndStoreCredential(TokenResponse, String)) aby przechowywać i uzyskiwać dane logowania umożliwiające dostęp do zabezpieczonych zasobów.
Jeśli nie używasz GoogleAuthorizationCodeFlow, możesz użyć klas niższego poziomu:
- Użyj DataStore.get(String), aby wczytać dane logowania z magazynu na podstawie identyfikatora użytkownika.
- Użyj GoogleAuthorizationCodeRequestUrl, aby przekierować przeglądarkę na stronę autoryzacji.
- Użyj AuthorizationCodeResponseUrl, by przetworzyć odpowiedź autoryzacji i przeanalizować kod autoryzacji.
- Użyj GoogleAuthorizationCodeTokenRequest, aby poprosić o token dostępu i ewentualnie token odświeżania.
- Utwórz nowe dane GoogleCredential i zapisz je w elemencie DataStore.set(String, V).
- Dostęp do zabezpieczonych zasobów przy użyciu:
GoogleCredential
. Wygasłe tokeny dostępu będą automatycznie odświeżane za pomocą tokena odświeżania (jeśli ma to zastosowanie). Pamiętaj, aby użyć funkcji DataStoreCredentialRefreshListener i ustawić ją dla danych logowania za pomocą GoogleCredential.Builder.addRefreshListener(CredentialRefreshListener).
Gdy skonfigurujesz projekt w konsoli interfejsów API Google, w zależności od używanego procesu. Więcej informacji znajdziesz w artykule Konfigurowanie OAuth 2.0. i Scenariusze korzystania z protokołu OAuth 2.0. Poniżej znajdziesz fragmenty kodu poszczególnych przepływów.
Aplikacje serwera WWW
Protokół tego procesu został opisany w Używanie OAuth 2.0 w aplikacjach serwera WWW.
Ta biblioteka udostępnia klasy pomocnicze serwletów, które znacznie upraszczają procedury kodu autoryzacji do podstawowych zastosowań. Wystarczy, że podasz konkretne podklasy zbioru danych AbstractAuthorizationCodeServlet i AbstractAuthorizationCodeCallbackServlet (z google-oauth-client-servlet) i dodaj je do pliku web.xml. Pamiętaj, że w dalszym ciągu musisz zadbać o użytkownika login w aplikacji internetowej i wyodrębnij identyfikator użytkownika.
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 } }
Aplikacje Google App Engine
Przepływ kodu autoryzacji w App Engine jest prawie taki sam jak serwlet przepływu kodu autoryzacji, z tym wyjątkiem, że możemy korzystać z mechanizmu Użytkownicy interfejsu Java API. Użytkownik użytkownik musi się zalogować, aby włączyć interfejs User Java API; . przekierowania użytkowników na stronę logowania, jeśli nie są jeszcze zalogowani, zapoznaj się z artykułem Zabezpieczenia i uwierzytelnianie (w pliku web.xml).
Podstawową różnicą w porównaniu z przypadkiem serwletu jest fakt, że podajesz
podklasy
AbstractAppEngineAuthorizationCodeServlet i AbstractAppEngineAuthorizationCodeCallbackServlet
(z google-oauth-client-appengine.
Rozszerzają one klasy abstrakcyjnych serwletów i implementują metodę getUserId
.
za pomocą interfejsu User Java API. AppEngineDataStoreFactory
(z google-http-client-appengine)
jest dobrym rozwiązaniem, jeśli chcesz zachować dane logowania przy użyciu danych Google App Engine
Store API.
Przykład wzięty (drobnie zmodyfikowany) z 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(); } }
Dodatkową próbkę znajdziesz tutaj: storage-serviceaccount-appengine-sample.
Konta usługi
GoogleCredential obsługuje też konta usługi. W przeciwieństwie do danych logowania, dla których aplikacja kliencka prosi o dostęp do danych użytkownika końcowego, konta usługi dają dostęp do do własnych danych. Twoja aplikacja kliencka podpisuje żądanie tokena dostępu za pomocą klucz prywatny pobrany z konsoli interfejsów API Google.
Przykładowy kod pobrany ze strony 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(); ...
Dodatkową próbkę znajdziesz tutaj: storage-serviceaccount-cmdline-sample.
Podszywanie się pod inne osoby
Możesz też użyć procedury konta usługi, aby podszywać się pod użytkownika w domenie, należące do domeny. Proces ten jest bardzo podobny do opisanego powyżej procesu tworzenia konta usługi, ale dodatkowo wywołaj GoogleCredential.Builder.setServiceAccountUser(String).
Zainstalowane aplikacje
Jest to przepływ kodu autoryzacji wiersza poleceń opisany w artykule Używanie protokołu OAuth 2.0 w zainstalowanych aplikacjach.
Przykładowy fragment kodu z: 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"); }
Aplikacje po stronie klienta
Aby użyć procesu klienckiego w przeglądarce opisanego w Używanie OAuth 2.0 w aplikacjach po stronie klienta wykonaj zwykle te czynności:
- Przekieruj użytkownika końcowego w przeglądarce na stronę autoryzacji za pomocą GoogleBrowserClientRequestUrl aby przyznać aplikacji przeglądarki dostęp do chronionych danych użytkownika.
- Użyj biblioteki klienta interfejsów API Google do obsługi JavaScriptu. aby przetworzyć token dostępu znaleziony we fragmencie adresu URL w identyfikatorze URI przekierowania zarejestrowana w Konsoli interfejsów API Google.
Przykład użycia aplikacji internetowej:
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
Której biblioteki należy używać z Androidem:
Jeśli tworzysz aplikacje na Androida i interfejs API Google, którego chcesz używać, jest uwzględniony w bibliotekę Usług Google Play, aby maksymalnie zwiększyć wydajność i wygodę korzystania z tej biblioteki. Jeśli interfejs API Google której chcesz używać z Androidem, nie jest częścią biblioteki Usług Google Play, może korzystać z biblioteki klienta interfejsu API Google dla języka Java, która obsługuje Androida 4.0 (Ice Cream Sandwich) (lub wyższego), co zostało opisane tutaj. Obsługa Androida w Biblioteka klienta API do języka Java to @Beta.
Informacje ogólne:
Od wersji Eclair (SDK 2.1) kontami użytkowników zarządza się na urządzeniu z Androidem za pomocą Menedżera konta. Autoryzacja wszystkich aplikacji na Androida odbywa się centralnie zarządzane przez pakiet SDK za pomocą AccountManager. Określasz zakres protokołu OAuth 2.0, którego potrzebuje Twoja aplikacja, a ona zwraca dostęp token.
Zakres protokołu OAuth 2.0 jest określany za pomocą parametru authTokenType
jako oauth2:
oraz zakres. Na przykład:
oauth2:https://www.googleapis.com/auth/tasks
Określa uprawnienia do zapisu i odczytu w interfejsie Google Tasks API. Jeśli potrzebujesz wielu zakresów OAuth 2.0 – użyj listy oddzielonej spacjami.
Niektóre interfejsy API mają specjalne parametry authTokenType
, które również działają. Przykład:
„Zarządzaj zadaniami” to alias dla przykładu authtokenType
widocznego powyżej.
Musisz też podać klucz interfejsu API z Konsola interfejsów API Google. W przeciwnym razie token otrzymany od AccountManagera udostępnia tylko anonimowy limit, który jest zwykle bardzo niski. Jeśli natomiast chcesz określić interfejs API, otrzymasz wyższy bezpłatny limit i możesz opcjonalnie skonfigurować rozliczenia za wykorzystanie powyżej tej wartości.
Przykładowy fragment kodu pobrany z 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; } }