Mi chiedo quale sia il modo migliore/più semplice per autenticare l'utente per l'API dei dati di Google in un'app desktop.API dati Google: come eseguire l'autenticazione per le applicazioni desktop
Ho letto il numero docs e sembra che le mie opzioni siano ClientLogin o OAuth.
Per ClientLogin, sembra che devo implementare l'interfaccia utente per login/password (e cose correlate come il salvataggio da qualche parte ecc.). Mi chiedo davvero se ci sia qualche supporto in più che potrebbe apparire una schermata di login/password predefinita e utilizzare il portachiavi del sistema operativo per memorizzare la password, ecc. Mi chiedo perché tale supporto non sia presente? Non sarebbe la procedura standard? Lasciando tale implementazione allo sviluppatore (beh, la possibilità di lasciare tale impl allo dev è ovviamente buona), direi che molte persone hanno trovato delle soluzioni molto brutte qui (quando volevano semplicemente incidere una piccola sceneggiatura).
OAuth sembra essere la soluzione migliore. Tuttavia, sembra che ci sia del codice mancante e/o la maggior parte del codice che ho trovato sembra essere rilevante solo per le applicazioni web. Esp., Ho seguito la documentazione e ottenuto here. Già nell'introduzione, parla dell'applicazione web. Successivamente, ho bisogno di specificare un URL di richiamata che non ha senso per un'applicazione desktop. Inoltre mi chiedo quale chiave/segreto del consumatore dovrei mettere in questo modo, inoltre, non ha senso per un'app desktop (specialmente per uno open source). Ho cercato un po 'in giro ed è stato detto here (on SO) che dovrei usare "anonimo"/"anonimo" come chiave del consumatore/segreto; ma dove si dice che nella documentazione di Google? E come ottengo il token dopo che l'utente si è autenticato da solo?
C'è qualche codice di esempio? (Non con un hardcoded username/password, ma con un metodo di autenticazione completa riutilizzabile.)
Grazie, Albert
Il mio codice finora:
import gdata.gauth
import gdata.contacts.client
CONSUMER_KEY = 'anonymous'
CONSUMER_SECRET = 'anonymous'
SCOPES = [ "https://www.google.com/m8/feeds/" ] # contacts
client = gdata.contacts.client.ContactsClient(source='Test app')
import BaseHTTPServer
import SocketServer
Handler = BaseHTTPServer.BaseHTTPRequestHandler
httpd = BaseHTTPServer.HTTPServer(("", 0), Handler)
_,port = httpd.server_address
oauth_callback_url = 'http://localhost:%d/get_access_token' % port
request_token = client.GetOAuthToken(
SCOPES, oauth_callback_url, CONSUMER_KEY, consumer_secret=CONSUMER_SECRET)
loginurl = request_token.generate_authorization_url(google_apps_domain=None)
loginurl = str(loginurl)
import webbrowser
webbrowser.open(loginurl)
Tuttavia, questo non funziona . Ho ricevuto questo errore:
Sorry, you've reached a login page for a domain that isn't using Google Apps. Please check the web address and try again.
Non lo capisco. Ovviamente non utilizzo Google Apps.
Ah, che l'errore è venuto da google_apps_domain=None
in generate_authorization_url
. Lasciare che via (cioè subito loginurl = request_token.generate_authorization_url()
e funziona finora
mio codice corrente:.
import gdata.gauth
import gdata.contacts.client
CONSUMER_KEY = 'anonymous'
CONSUMER_SECRET = 'anonymous'
SCOPES = [ "https://www.google.com/m8/feeds/" ] # contacts
client = gdata.contacts.client.ContactsClient(source='Test app')
import BaseHTTPServer
import SocketServer
httpd_access_token_callback = None
class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
if self.path.startswith("/get_access_token?"):
global httpd_access_token_callback
httpd_access_token_callback = self.path
self.send_response(200)
def log_message(self, format, *args): pass
httpd = BaseHTTPServer.HTTPServer(("", 0), Handler)
_,port = httpd.server_address
oauth_callback_url = 'http://localhost:%d/get_access_token' % port
request_token = client.GetOAuthToken(
SCOPES, oauth_callback_url, CONSUMER_KEY, consumer_secret=CONSUMER_SECRET)
loginurl = request_token.generate_authorization_url()
loginurl = str(loginurl)
print "opening oauth login page ..."
import webbrowser; webbrowser.open(loginurl)
print "waiting for redirect callback ..."
while httpd_access_token_callback == None:
httpd.handle_request()
print "done"
request_token = gdata.gauth.AuthorizeRequestToken(request_token, httpd_access_token_callback)
# Upgrade the token and save in the user's datastore
access_token = client.GetAccessToken(request_token)
client.auth_token = access_token
che aprirà la pagina di Google OAuth con il suggerimento in fondo:
This website has not registered with Google to establish a secure connection for authorization requests. We recommend that you deny access unless you trust the website.
E ' tuttavia, non funziona ancora. Quando provo ad accedere ai contatti (ovvero solo a client.GetContacts()
), viene visualizzato questo errore:
gdata.client.Unauthorized: Unauthorized - Server responded with: 401, <HTML>
<HEAD>
<TITLE>Token invalid - AuthSub token has wrong scope</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>Token invalid - AuthSub token has wrong scope</H1>
<H2>Error 401</H2>
</BODY>
</HTML>
Ok, sembra che abbia davvero impostato l'ambito sbagliato. Quando utilizzo http
anziché https
(ad esempio SCOPES = [ "http://www.google.com/m8/feeds/" ]
), funziona.
Ma mi piacerebbe davvero usare https. Mi chiedo come posso farlo.
Inoltre, un altro problema con questa soluzione:
Nell'elenco di accesso autorizzato al mio account Google, ora ho un po 'di tali voci localhost:
localhost:58630 — Google Contacts [ Revoke Access ]
localhost:58559 — Google Contacts [ Revoke Access ]
localhost:58815 — Google Contacts [ Revoke Access ]
localhost:59174 — Google Contacts [ Revoke Access ]
localhost:58514 — Google Contacts [ Revoke Access ]
localhost:58533 — Google Contacts [ Revoke Access ]
localhost:58790 — Google Contacts [ Revoke Access ]
localhost:59012 — Google Contacts [ Revoke Access ]
localhost:59191 — Google Contacts [ Revoke Access ]
Mi chiedo come Posso evitare che farà tali voci.
Quando utilizzo xoauth_displayname
, visualizza invece quel nome ma crea ancora più voci (probabilmente perché l'URL è ancora in gran parte diverso (a causa della porta) ogni volta). Come posso evitarlo?
Il mio codice attuale è ora Github.
Mi chiedo anche, dove, come e per quanto tempo devo conservare il token di accesso e/o il token richiesta in modo che l'utente non viene chiesto sempre più e più volte ogni volta quando l'utente avvia l'applicazione.
L'autorizzazione da parte dell'utente - esattamente come farebbe quello sguardo piace? Aprirò un browser esterno e in qualche modo ricontrollare frequentemente se il token è stato autorizzato? Nel codice di esempio, non vedo realmente dove viene aperto il browser. – Albert
Inoltre, sembra che la lib di gdata abbia già delle funzioni per OAuth. Quindi immagino di non aver bisogno di un'altra lib per quello? O cosa fornisce python-oauth2 oltre a quello che ho già con gdata? – Albert
OAuth a tre vie funziona in questo modo: 1. Richiede un token e un token secret dal provider (Google) 2.Si apre un browser per l'utente e lo si accede all'URL di autorizzazione del provider in cui l'utente può confermare che vorrebbe concedere l'accesso e si ottiene un codice di verifica. Il sito del fornitore può richiamarti tramite un URL che fornisce il verificatore o fornire all'utente il codice di verifica di cui hai bisogno. 3. con il token originale e il verificatore è possibile acquisire il token finale dal fornitore. – ldx