Panoramica
Scopo: il presente documento spiega come utilizzare i GoogleCredential per eseguire l'autorizzazione OAuth 2.0 con i servizi Google. Per per informazioni sulle funzioni generiche di OAuth 2.0 fornite, consulta OAuth 2.0 e libreria client OAuth di Google per Java.
Riepilogo:per accedere ai dati protetti archiviati sui servizi Google, usa OAuth 2.0 per l'autorizzazione. Le API di Google supportano i flussi OAuth 2.0 per diversi tipi di applicazioni client. In tutti questi flussi, l'applicazione client richiede un token di accesso associati solo alla tua applicazione client e al proprietario dei dati protetti a cui l'utente accede. Il token di accesso è associato anche a un ambito limitato che definisce il tipo di dati a cui ha accesso l'applicazione client (ad esempio "Gestisci le tue attività"). Un obiettivo importante di OAuth 2.0 è garantire un comodo accesso ai dati protetti, riducendo al minimo il potenziale impatto in caso di furto di un token di accesso.
I pacchetti OAuth 2.0 nella libreria client dell'API di Google per Java sono basati su per uso generico Libreria client OAuth 2.0 di Google per Java.
Per maggiori dettagli, consulta la documentazione Javadoc per i seguenti pacchetti:
- com.google.api.client.googleapis.auth.oauth2 (da google-api-client)
- com.google.api.client.googleapis.extensions.appengine.auth.oauth2 (da google-api-client-appengine)
Console API di Google
Prima di poter accedere alle API di Google, devi configurare un progetto nella Console API di Google per autenticazione e fatturazione il client sia un'applicazione installata, un'applicazione mobile, un server web o un client eseguito nel browser.
Per istruzioni su come configurare correttamente le credenziali, consulta le Guida della Console API.
Credenziale
GoogleCredential
GoogleCredential è una classe di supporto thread-safe per OAuth 2.0 che consente di accedere alle risorse protette usando un token di accesso. Ad esempio, se disponi già di un token di accesso, può effettuare una richiesta nel seguente modo:
GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken); Plus plus = new Plus.builder(new NetHttpTransport(), GsonFactory.getDefaultInstance(), credential) .setApplicationName("Google-PlusSample/1.0") .build();
Identità Google App Engine
Questa credenziale alternativa si basa sul API Java App Engine App Engine. A differenza della credenziale con cui un'applicazione client richiede l'accesso a un i dati dell'utente finale, l'API App Identity fornisce l'accesso al client dell'applicazione.
Usa AppIdentityCredential (da google-api-client-appengine). Questa credenziale è molto più semplice perché Google App Engine si occupa di tutte i dettagli. Devi specificare solo l'ambito OAuth 2.0 di cui hai bisogno.
Esempio di codice tratto da 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(); }
Datastore
Generalmente un token di accesso ha una data di scadenza di un'ora, dopodiché dovrai
ricevi un messaggio di errore se provi a utilizzarlo.
GoogleCredential
si occupa di "aggiornare" automaticamente il token, il che significa semplicemente
un nuovo token di accesso. Ciò viene fatto per mezzo di un token di aggiornamento di lunga durata, che
viene generalmente ricevuto insieme al token di accesso se utilizzi
Parametro access_type=offline
durante il flusso del codice di autorizzazione (vedi
GoogleAuthorizationCodeFlow.Builder.setAccessType(String)).
La maggior parte delle applicazioni dovrà mantenere il token di accesso della credenziale e/o token di aggiornamento. Per mantenere i token di accesso e/o di aggiornamento della credenziale, puoi: Fornire la tua implementazione di DataStoreFactory con StoredCredential; In alternativa, puoi utilizzare una delle seguenti implementazioni fornite dalla libreria:
- AppEngineDataStoreFactory: rende permanente la credenziale utilizzando l'API Google App Engine Data Store.
- MemoryDataStoreFactory: "persiste" la credenziale in memoria, che è utile solo come spazio di archiviazione a breve termine per l'intera durata del processo.
- FileDataStoreFactory: rende la credenziale permanente in un file.
Utenti AppEngine: AppEngineCredentialStore è deprecato e verrà rimosso a breve. Ti consigliamo di utilizzare AppEngineDataStoreFactory con StoredCredential. Se le credenziali sono archiviate alla vecchia maniera, puoi utilizzare metodi helper migrateTo(AppEngineDataStoreFactory) o migrateTo(DataStore) per eseguire la migrazione.
Puoi utilizzare DataStoreCredentialRefreshListener e impostala per la credenziale utilizzando GoogleCredential.Builder.addRefreshListener(CredentialRefreshListener)).
Flusso del codice di autorizzazione
Utilizza il flusso del codice di autorizzazione per consentire all'utente finale di concedere la tua applicazione ai propri dati protetti nelle API di Google. Il protocollo per questo flusso è specificato in Concessione del codice di autorizzazione.
Questo flusso è implementato utilizzando GoogleAuthorizationCodeFlow. I passaggi sono:
- L'utente finale accede all'applicazione. Dovrai associare l'utente con un ID utente univoco per la tua applicazione.
- Chiama AuthorizationCodeFlow.loadCredential(String)). in base all'ID utente per verificare se le credenziali dell'utente finale sono già note. Se è così, non devi fare altro.
- In caso contrario, chiama AuthorizationCodeFlow.newAuthorizationUrl() e indirizzare il browser dell'utente finale a una pagina di autorizzazione per concedere l'accesso delle applicazioni ai propri dati protetti.
- Il server di autorizzazione di Google reindirizzerà quindi il browser alla
URL di reindirizzamento specificato dalla tua applicazione, insieme a una query
code
. Utilizza il parametrocode
per richiedere un token di accesso utilizzando AuthorizationCodeFlow.newTokenRequest(String)). - Usa AuthorizationCodeFlow.createAndStoreCredential(TokenResponse, String)) per archiviare e ottenere una credenziale per accedere alle risorse protette.
In alternativa, se non utilizzi GoogleAuthorizationCodeFlow, puoi utilizzare le classi di livello inferiore:
- Utilizza DataStore.get(String) per caricare la credenziale dallo store in base all'ID utente.
- Utilizza GoogleAuthorizationCodeRequestUrl per indirizzare il browser alla pagina di autorizzazione.
- Utilizza AuthorizationCodeResponseUrl per elaborare la risposta di autorizzazione e analizzare il codice di autorizzazione.
- Utilizza GoogleAuthorizationCodeTokenRequest per richiedere un token di accesso ed eventualmente un token di aggiornamento.
- Crea una nuova GoogleCredential e memorizzala utilizzando DataStore.set(String, V).
- Accedi alle risorse protette utilizzando
GoogleCredential
. I token di accesso scaduti verranno aggiornati automaticamente utilizzando il token di aggiornamento (se applicabile). Assicurati di utilizzare DataStoreCredentialRefreshListener e impostarlo per la credenziale utilizzando GoogleCredential.Builder.addRefreshListener(CredentialRefreshListener)).
Quando configuri il tuo progetto nella console API di Google, che selezioni tra le diverse credenziali, a seconda del flusso che stai utilizzando. Per maggiori dettagli, consulta l'articolo Configurare OAuth 2.0. e scenari OAuth 2.0. Di seguito sono riportati snippet di codice per ogni flusso.
Applicazioni server web
Il protocollo per questo flusso è spiegato in Utilizzo di OAuth 2.0 per applicazioni server web.
Questa libreria fornisce classi helper servlet per semplificare significativamente del codice di autorizzazione per casi d'uso di base. Devi solo fornire sottoclassi concrete di AbstractAuthorizationCodeServlet e AbstractAuthorizationCodeCallbackServlet (da google-oauth-client-servlet) e aggiungerli al file web.xml. Tieni presente che devi ancora occuparti del cliente per la tua applicazione web ed estrarre un ID utente.
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 } }
Applicazioni di Google App Engine
Il flusso del codice di autorizzazione su App Engine è quasi identico al servlet del codice di autorizzazione, con la differenza che possiamo sfruttare API Users Java. L'utente deve aver effettuato l'accesso per abilitare l'API Users Java. per informazioni su reindirizzare gli utenti a una pagina di accesso nel caso in cui non abbiano già eseguito l'accesso, vedi Sicurezza e autenticazione (in web.xml).
La differenza principale rispetto al caso servlet è che fornisci informazioni
delle sottoclassi
AbstractAppEngineAuthorizationCodeServlet e AbstractAppEngineAuthorizationCodeCallbackServlet
(da google-oauth-client-appengine.
Estendono le classi servlet astratte e implementano il metodo getUserId
utilizzando l'API Users Java. AppEngineDataStoreFactory
(da google-http-client-appengine)
è una buona opzione per mantenere la credenziale in modo permanente utilizzando i dati di Google App Engine
API Store.
Esempio preso (leggermente modificato) da 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(); } }
Per un esempio aggiuntivo, vedi storage-serviceaccount-appengine-sample.
Account di servizio
GoogleCredential Supporta anche gli account di servizio. A differenza della credenziale con cui un'applicazione client richiede l'accesso a un i dati dell'utente finale, gli account di servizio forniscono l'accesso ai dati dati personali. L'applicazione client firma la richiesta di un token di accesso utilizzando Una chiave privata scaricata dalla console API di Google.
Codice di esempio preso da 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(); ...
Per un esempio aggiuntivo, vedi storage-serviceaccount-cmdline-sample.
Furto d'identità
Puoi anche utilizzare il flusso dell'account di servizio per impersonare un utente in un dominio che che possiedi. È molto simile al flusso degli account di servizio qui sopra, ma inoltre chiama GoogleCredential.Builder.setServiceAccountUser(String).
Applicazioni installate
Si tratta del flusso del codice di autorizzazione dalla riga di comando descritto in Utilizzo di OAuth 2.0 per le applicazioni installate.
Snippet di esempio da 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"); }
Applicazioni lato client
Per utilizzare il flusso client basato su browser descritto in Con OAuth 2.0 per le applicazioni lato client, devi generalmente seguire questa procedura:
- Reindirizza l'utente finale nel browser alla pagina di autorizzazione utilizzando GoogleBrowserClientRequestUrl per concedere alla tua applicazione del browser l'accesso ai dati protetti dell'utente finale.
- Utilizza la libreria client dell'API di Google per JavaScript. per elaborare il token di accesso trovato nel frammento dell'URL all'URI di reindirizzamento registrati nella console API di Google.
Utilizzo di esempio per un'applicazione web:
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
Quale libreria utilizzare con Android:
Se stai sviluppando per Android e l'API di Google che vuoi utilizzare è inclusa nel libreria di Google Play Services, usala per ottenere prestazioni ed esperienza ottimali. Se l'API di Google che vuoi utilizzare con Android non fa parte della libreria Google Play Services, puoi utilizzare la libreria client dell'API di Google per Java, che supporta Android 4.0 (Ice Cream Sandwich) (o superiore) e come descritto qui. Il supporto per Android nel Google La libreria client dell'API per Java è @Beta.
Informazioni di base:
A partire da Eclair (SDK 2.1), gli account utente vengono gestiti su un dispositivo Android utilizzando l'account manager. L'autorizzazione di tutte le applicazioni Android è centralizzata gestite dall'SDK AccountManager Tu specifichi l'ambito OAuth 2.0 richiesto dalla tua applicazione, che restituirà un accesso da utilizzare.
L'ambito OAuth 2.0 viene specificato tramite il parametro authTokenType
come oauth2:
più l'ambito. Ad esempio:
oauth2:https://www.googleapis.com/auth/tasks
Specifica l'accesso in lettura/scrittura all'API Google Tasks. Se hai bisogno di più Ambiti OAuth 2.0, utilizza un elenco separato da spazi.
Alcune API hanno parametri authTokenType
speciali che funzionano. Ad esempio:
"Gestisci le tue attività" è un alias per l'esempio authtokenType
mostrato sopra.
Devi inoltre specificare la chiave API nel Console API di Google. In caso contrario, il token che ti viene fornito dall'AccountManager ti fornisce quota anonima, che di solito è molto bassa. Al contrario, specificando un'API chiave ricevi una quota senza costi più alta e, se vuoi, puoi configurare la fatturazione per l'utilizzo al di sopra di questo.
Esempio di snippet di codice tratto da 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; } }