Мне интересно, как лучше / проще всего аутентифицировать пользователя для API данных Google в настольном приложении.
Я прочитал документы , и мне кажется, что мой варианты: ClientLogin или OAuth.
Что касается ClientLogin, мне кажется, что я должен сам реализовать пользовательский интерфейс для входа / пароля (и связанных вещей, таких как сохранение где-нибудь и т. д.). Мне действительно интересно, есть ли там еще какая-то поддержка, которая может вызвать экран входа / пароля по умолчанию и использовать связку ключей ОС для хранения пароля и т. Д. Интересно, почему такой поддержки нет? Разве это не стандартная процедура? Оставив эту реализацию разработчику (ну, конечно, возможность оставить это разработчику - это хорошо), Я предполагаю, что многие люди придумали здесь очень уродливые решения (когда они просто хотели собрать небольшой скрипт).
OAuth кажется лучшим решением. Тем не менее, похоже, что какой-то код отсутствует, и / или большая часть кода, который я нашел, кажется актуальным только для веб-приложений. Например, я следил за документацией и получил здесь . Уже во введении говорится о веб-приложении. Позже мне нужно указать 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 Apps. Проверьте веб-адрес и повторите попытку.
Я не совсем понимаю. Конечно, я не использую Google Apps.
А, эта ошибка возникла из-за 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,
Token invalid - AuthSub token has wrong scope
Token invalid - AuthSub token has wrong scope
Error 401
Хорошо, похоже, что я действительно установил неправильную область. Когда я использую http
вместо https
(т.е. SCOPES = ["http://www.google.com/m8/feeds/"]
), он работает.
Но я бы очень хотел использовать https. Интересно, как я могу это сделать.
Также есть еще одна проблема с этим решением:
В списке авторизованного доступа к моей учетной записи Google теперь есть несколько таких записей localhost:
localhost: 58630 - Google Контакты [Отменить доступ]
Когда я используюhttp
вместоhttps
(т.е.SCOPES = ["http://www.google.com/m8/feeds/"]
), он работает.Но я бы очень хотел использовать https. Интересно, как я могу это сделать.
Также есть еще одна проблема с этим решением:
В списке авторизованного доступа к моей учетной записи Google теперь есть несколько таких записей localhost:
localhost: 58630 - Google Контакты [Отменить доступ]
Когда я использую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 [Отменить доступ]Интересно, как я могу избежать таких записей.
Когда я использую
xoauth_displayname
, вместо этого отображается это имя, но все же выполняется несколько записей (возможно, потому, что URL-адрес по-прежнему в основном различается (из-за порта) каждый раз). Как мне этого избежать?Мой текущий код теперь на Github .
Мне также интересно, где, как и как долго мне следует хранить токен доступа и / или токен запроса, чтобы что пользователя не спрашивают всегда снова и снова каждый раз, когда пользователь запускает приложение.