API данных Google: как выполнить аутентификацию для настольных приложений - PullRequest
7 голосов
/ 09 февраля 2011

Я задаюсь вопросом о лучшем / простом способе аутентификации пользователя для 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 .


Мне также интересно, где, как и как долго я должен хранить токен доступа и / или токен запроса, чтобы пользователь не былспрашивается всегда снова и снова каждый раз, когда пользователь запускает приложение.

Ответы [ 2 ]

2 голосов
/ 01 мая 2012

Это способ аутентификации в Google с помощью приложения для настольного компьютера. (Вот как я это сделал) https://developers.google.com/accounts/docs/OAuth2InstalledApp https://developers.google.com/accounts/docs/OAuth2Login

Тест: https://www.googleapis.com/oauth2/v1/userinfo?access_token=ACCESS_TOKEN

2 голосов
/ 09 февраля 2011

OAuth можно использовать и в настольных приложениях.Ключ пользователя и секретный «анонимный» идеально подходят для такого приложения.

Пользователь не будет аутентифицировать себя.Вы получите токен от поставщика (Google), а затем он будет авторизован пользователем как токен для доверенного потребителя (вашего приложения), с помощью которого можно получать доступ к его службам Google.

Вот хорошая библиотека Python для OAuth:

https://github.com/simplegeo/python-oauth2

Вот краткий обзор того, как работает OAuth:

http://blog.doityourselfandroid.com/2010/11/07/google-oauth-overview/

Вотпример для Java, который также объясняет шаги, которые необходимо предпринять для аутентификации OAuth:

http://nilvec.com/implementing-client-side-oauth-on-android/

HTH.

...