2012-09-18 12 views
11

Ho installato ed eseguito correttamente lo Google Drive Quick Start application called DriveCommandLine. L'ho anche adattato un po 'per ottenere informazioni sui file per uno dei file nel mio account Drive.Google Drive/OAuth - Impossibile capire come riutilizzare GoogleCredentials

Quello che mi piacerebbe fare ora è salvare le credenziali in qualche modo e riutilizzarle senza che l'utente debba visitare una pagina Web ogni volta per ottenere un codice di autorizzazione. Ho controllato this page con le istruzioni per recuperare e utilizzare le credenziali OAuth 2.0. Per poter utilizzare la classe di esempio (MyClass), ho modificato la riga nel DriveCommandLine dove l'oggetto credenziali è un'istanza:

Credential credential = MyClass.getCredentials(code, ""); 

Ciò risulta nella seguente eccezione eccezioni:

java.lang.NullPointerException 
    at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:187) 
    at com.google.api.client.json.jackson.JacksonFactory.createJsonParser(JacksonFactory.java:84) 
    at com.google.api.client.json.JsonFactory.fromInputStream(JsonFactory.java:247) 
    at com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets.load(GoogleClientSecrets.java:168) 
    at googledrive.MyClass.getFlow(MyClass.java:145) 
    at googledrive.MyClass.exchangeCode(MyClass.java:166) 
    at googledrive.MyClass.getCredentials(MyClass.java:239) 
    at googledrive.DriveCommandLine.<init>(DriveCommandLine.java:56) 
    at googledrive.DriveCommandLine.main(DriveCommandLine.java:115) 

I' Ho guardato queste API (Google Drive e OAuth) per 2 giorni e ho fatto pochissimi progressi. Apprezzerei molto l'aiuto dell'errore sopra riportato e il problema di ottenere credenziali persistenti in generale.

Questa intera struttura mi sembra inutilmente complicata. Qualcuno si preoccupa di spiegare perché non posso semplicemente creare un oggetto credenziale semplice passando il mio nome utente e password Google?

Grazie, Brian O Carroll, Dublino, Irlanda

* Aggiornamento *

Ok, ho appena ottenuto intorno l'errore precedente e ora ho una nuova.

Il modo in cui ho risolto il problema è stato la modifica di MyClass.getFlow(). Invece di creare un oggetto GoogleClientServices da un file JSON, ho usato una versione diversa di GoogleAuthorizationCodeFlow.Builder che permette di immettere l'ID cliente e cliente segreto direttamente come stringhe:

flow = new GoogleAuthorizationCodeFlow.Builder(httpTransport, jsonFactory, "<MY CLIENT ID>", "<MY CLIENT SECRET>", SCOPES).setAccessType("offline").setApprovalPrompt("force").build(); 

Il problema che ho ora è che ottengo il seguente errore quando si tenta di utilizzare il flusso (oggetto GoogleAuthorizationCodeFlow) per scambiare il codice di autorizzazione per le credenziali oggetto:

An error occurred: com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request 
{ 
    "error" : "invalid_scope" 
} 
googledrive.MyClass$CodeExchangeException 
     at googledrive.MyClass.exchangeCode(MyClass.java:185) 
     at googledrive.MyClass.getCredentials(MyClass.java:262) 
     at googledrive.DriveCommandLine.<init>(DriveCommandLine.java:56) 
     at googledrive.DriveCommandLine.main(DriveCommandLine.java:115) 

c'è qualche altro ambito dovrei usare per questo? Attualmente sto usando la gamma di ambiti forniti con MyClass:

private static final List<String> SCOPES = Arrays.asList(
     "https://www.googleapis.com/auth/drive.file", 
     "https://www.googleapis.com/auth/userinfo.email", 
     "https://www.googleapis.com/auth/userinfo.profile"); 

Grazie!

risposta

13

Sento il tuo dolore. Sono due mesi e sono ancora sorpreso.

Alcuni dei miei insegnamenti ...

  • Quando si richiede autorizzazioni utente, specificare "non in linea = true". Questo ("a volte" sic) restituirà un refreshtoken, che è buono come una password con permessi limitati. È possibile memorizzare questo e riutilizzarlo in qualsiasi momento (fino a quando l'utente lo revoca) per recuperare un token di accesso.

  • La mia sensazione è che gli SDK di Google siano più di un aiuto che di aiuto. Uno per uno, ho smesso di usarli e ora richiama direttamente l'API REST.

  • Sul tuo ultimo punto, puoi (solo) utilizzare il protocollo clientlogin di Google per accedere alla generazione precedente di API. Tuttavia questo è totalmente deprecato e sarà presto disattivato. OAuth è progettato per fornire un controllo delle autorizzazioni a grana fine che è intrinsecamente complesso. Quindi, anche se sono d'accordo, è complicato, non penso che sia inutilmente così. Viviamo in un mondo complicato :-)

la vostra e la miniera esperienze dimostrano che la comunità di sviluppo è ancora bisogno di un documento e ricette consolidata per ottenere questa roba nei nostri specchi retrovisori in modo che possiamo concentrarsi su il compito a portata di mano.

+0

Grazie pinoyyid, mi dispiace aggiunto accidentalmente una modifica/aggiornamento al tuo post, invece del mio. Mi sto ancora abituando a postare qui! Proverò a implementare i tuoi suggerimenti e ti farò sapere come va. PS - Sfortunatamente, non ho 2 mesi per lavorare su questo. Sono infastidito dal fatto che ho già trascorso 2 giorni !! : -/ –

+0

Riguardo al ritorno di frefreshtoken. Ho creato un'applicazione server pensata per funzionare senza alcuna interazione da parte dell'utente dopo la configurazione.Ma per alcuni giorni fa (è in corso da 2 mesi senza problemi) è stato visto che più pagine di Auth sono state aperte sul server, per richiedere l'accesso all'applicazione per utilizzare Google Drive. Anche se chiedeva Auth, funzionava ancora. Qualche indizio sul perché ciò avvenga? –

+0

dovrebbe probabilmente essere una domanda separata. Vedo anche questo e lo metto giù in Google in modo casuale in scadenza il token di aggiornamento. Cerca una sovvenzione di 400 non valida nei tuoi registri per vedere se questa è la causa. È possibile che la tua app richieda un token di aggiornamento da più postazioni? Credo che, se questo è il caso, i nuovi token di aggiornamento possono far scadere quelli vecchi. – pinoyyid

1

Ok, ho finalmente risolto il secondo problema sopra e finalmente ho trovato un oggetto GoogleCredential funzionante con un token di accesso e un token di aggiornamento.

Ho continuato a provare a risolvere il problema degli ambiti modificando l'elenco degli ambiti in MyClass (quello che gestisce le credenziali). Alla fine ho dovuto regolare gli ambiti nella mia versione modificata di DriveCommandLine (quello che è stato originariamente utilizzato per ottenere un codice di autorizzazione). Ho aggiunto 2 portate da Oauth2Scopes:

GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
    httpTransport, jsonFactory, CLIENT_ID, CLIENT_SECRET, 
    Arrays.asList(DriveScopes.DRIVE, Oauth2Scopes.USERINFO_EMAIL, Oauth2Scopes.USERINFO_PROFILE)) 
    .setAccessType("offline").setApprovalPrompt("force").build(); 

Aggiungendo gli ambiti per le informazioni utente mi ha permesso di ottenere l'ID utente più avanti in MyClass. Ora posso usare l'ID utente per memorizzare le credenziali in un database per riutilizzarle (senza dover chiedere all'utente di andare a un URL ogni volta). Ho anche impostato il tipo di accesso su "offline" come suggerito da pinoyyid.

3

Oath2Scopes viene importato come segue:

import com.google.api.services.oauth2.Oauth2Scopes; 

È necessario avere il file jar 'google-API-servizi-OAuth2-v2-rev15-1.8.0-beta.jar' nel percorso classe per accedi a quel pacchetto. Può essere scaricato here.

No, non so come ottenere le credenziali senza dover visitare l'URL di autorizzazione almeno una volta e copiare il codice. Ho modificato MyClass per archiviare e recuperare le credenziali da un database (nel mio caso, è una semplice tabella che contiene userid, accesstoken e refreshtoken). In questo modo devo solo ottenere il codice di autorizzazione una volta e una volta ottenuto i token di accesso/aggiornamento, posso riutilizzarli per creare un oggetto GoogleCredential. Ecco come Imake l'oggetto GoogleCredential:

GoogleCredential credential = new GoogleCredential.Builder().setJsonFactory(jsonFactory) 
      .setTransport(httpTransport).setClientSecrets(clientid, clientsecret).build(); 
    credential.setAccessToken(accessToken); 
    credential.setRefreshToken(refreshToken); 

basta inserire il tuo clientid, clientsecret, access token e refreshToken sopra.

Non ho davvero molto tempo per separare e riordinare tutto il mio codice per postarlo qui ma se hai ancora problemi, fammelo sapere e vedrò cosa posso fare. Sebbene tu stia effettivamente chiedendo a un cieco una direzione. La mia comprensione di questo intero sistema è molto approssimativa!

Cheers, Brian

Problemi correlati