Я задаюсь вопросом о лучшем / простом способе аутентификации пользователя для API данных Google в настольном приложении.
Я прочитал документы , и мне кажется, что я могу выбрать ClientLoginили OAuth.
Для ClientLogin кажется, что мне нужно реализовать пользовательский интерфейс для логина / пароля (и связанных с этим вещей, таких как сохранение этого где-то и т. д.).Мне действительно интересно, есть ли еще какая-то поддержка, которая может вызвать экран логина / пароля по умолчанию и использовать цепочку ключей ОС для хранения пароля и т. Д. Интересно, почему такой поддержки нет?Разве это не будет стандартной процедурой?Предоставив эту реализацию разработчику (ну, конечно, возможность оставить это значение для разработчика - это хорошо), я бы предположил, что многие люди придумали очень уродливые решения здесь (когда они просто хотели взломать небольшой скрипт).
OAuth кажется лучшим решением.Однако, кажется, что некоторый код отсутствует, и / или большая часть кода, который я нашел, кажется, имеет отношение только к веб-приложениям.Esp., Я следовал за документацией и получил здесь .Уже во вступлении речь идет о веб-приложении.Затем мне нужно указать URL обратного вызова, который не имеет смысла для настольного приложения.Также мне интересно, какой потребительский ключ / секрет я должен указать, поскольку он также не имеет смысла для настольного приложения (особенно не для открытого исходного кода).Я искал немного вокруг, и было сказано здесь (на SO) , что я должен использовать «анонимный» / «анонимный» в качестве ключа / секрета потребителя;но где это сказано в документации гугла?И как я могу получить токен после того, как пользователь аутентифицирует себя?
Есть ли пример кода?(Не с жестко запрограммированным именем пользователя / паролем, но с помощью многоразового метода полной аутентификации.)
Спасибо, Альберт
Пока мой код:
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)
Однако, это не работает.Я получаю эту ошибку:
Извините, вы достигли страницы входа в домен, который не использует Службы Google.Пожалуйста, проверьте веб-адрес и попробуйте снова.
Я не совсем понимаю.Конечно, я не пользуюсь Службами Google.
Ах, эта ошибка произошла от google_apps_domain=None
в generate_authorization_url
.Оставьте это (т. Е. Просто loginurl = request_token.generate_authorization_url()
, и это пока работает.
Мой текущий код:
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
Это откроет страницу Google OAuth с подсказкой внизу:
Этот веб-сайт не зарегистрирован в Google для установки безопасного соединения для запросов на авторизацию. Мы рекомендуем запрещать доступ, если вы не доверяете веб-сайту.
Он по-прежнему не работаетОднако, когда я пытаюсь получить доступ к контактам (то есть просто client.GetContacts()
), я получаю эту ошибку:
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>
Хорошо, кажется, что я действительно установил неправильную область. КогдаЯ использую http
вместо https
(то есть SCOPES = [ "http://www.google.com/m8/feeds/" ]
), это работает.
Но я действительно хотел бы использовать https. Интересно, как я могу это сделать.
Кроме того, еще одна проблема с этим решением:
В списке авторизованного доступа к моей учетной записи Google у меня теперь есть куча таких записей localhost:
localhost: 58630 -Контакты Google [Отзыв доступа]
localhost: 58559 - Контакты Google [Отзыв доступа]
localhost: 58815 - Контакты Google [отозвать доступ]
localhost: 59174 - Контакты Google [отменить доступ]
localhost: 58514 - Контакты Google [Отменить доступ]
localhost: 58533 - Контакты Google [Отменить доступ]
localhost: 58790 - контакты Google [отозвать доступ]
localhost: 59012 - контакты Google [отозвать доступ]
localhost: 59191 - контакты Google [отозвать доступ]
IИнтересно, как я могу избежать, что он будет делать такие записи.
Когда я использую xoauth_displayname
, он отображает это имя вместо этого, но по-прежнему делает несколько записей (вероятно, потому что URL по-прежнему в основном отличается (из-за порта)каждый раз).Как я могу избежать этого?
Мой текущий code теперь на Github .
Мне также интересно, где, как и как долго я должен хранить токен доступа и / или токен запроса, чтобы пользователь не былспрашивается всегда снова и снова каждый раз, когда пользователь запускает приложение.