Интересно, лучший или простой способ аутентификации пользователя API Google Data в настольном приложении.API данных Google: как сделать аутентификацию для настольных приложений
Я прочитал docs, и кажется, что мои варианты - ClientLogin или OAuth.
Для ClientLogin мне кажется, что я должен реализовать пользовательский интерфейс для входа/пароля (и связанных с ним вещей, таких как сохранение этого где-нибудь и т. Д.). Мне действительно интересно, есть ли там какая-то дополнительная поддержка, которая может появиться по умолчанию для экрана входа/пароля по умолчанию и использует брелок OS для хранения пароля и т. Д. Мне интересно, почему такой поддержки нет? Разве это не стандартная процедура? Отправляя эту реализацию разработчику (ну, конечно, возможность оставить это приложение для разработчика хороша), я бы предположил, что многие люди придумали очень уродливые решения здесь (когда они просто хотели взломать небольшой скрипт).
OAuth кажется лучшим решением. Тем не менее, кажется, что какой-то код отсутствует и/или большинство найденных мной кодов кажется только релевантным для веб-приложений. Esp., Я следил за документацией и получил here. Уже во введении говорится о веб-приложении. Затем, позже, мне нужно указать URL-адрес обратного вызова, который не имеет смысла для настольного приложения. Также мне интересно, какой потребительский ключ/секрет я должен поставить, что также не имеет смысла для настольного приложения (например, не для open-source). Я немного искал, и было сказано here (on SO), что я должен использовать «анонимный»/«анонимный» как ключ/секрет потребителя; но где говорится, что в документации Google? И как мне получить токен после того, как пользователь аутентифицировал себя?
Есть ли пример кода? (Не с закодированным именем пользователя/паролем, но с многоразовым полным методом проверки подлинности.)
Спасибо, Альбертом
Моего кода до сих пор:
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)
Однако, это не работает , Я получаю эту ошибку:
Sorry, you've reached a login page for a domain that isn't using Google Apps. Please check the web address and try again.
Я не совсем понимаю это. Конечно, я не использую 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 с намеком на дне:
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.
Это Однако, когда я пытаюсь получить доступ к контактам (например, только 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 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 ]
Интересно, как Я могу избежать того, что он сделает такие записи.
Когда я использую xoauth_displayname
, он отображает это имя вместо этого, но все же делает несколько записей (вероятно, потому, что URL-адрес по-прежнему в основном отличается (из-за порта) каждый раз). Как я могу избежать этого?
Текущий код сейчас на Github.
Я также задаюсь вопросом, где, как и как долго я должен хранить маркер доступа и/или маркер запроса, так что пользователь не задал всегда снова и снова каждый раз, когда пользователь запускает приложение.
Разрешение пользователем - как именно бы это выглядело как? Открывать внешний веб-браузер и как-то перепроверять часто, если токен разрешен? В примере кода я действительно не вижу, где открыт веб-браузер. – Albert
Кроме того, похоже, что gdata lib уже поставляется с функциями для OAuth. Так что, я думаю, для этого мне не нужна другая библиотека? Или что делает python-oauth2 в дополнение к тому, что у меня уже есть с gdata? – Albert
Трехсторонний OAuth работает следующим образом: 1. Вы запрашиваете токен и токен от поставщика (Google) 2.Вы открываете веб-браузер для пользователя и отправляете его на URL-адрес авторизации провайдера, где пользователь может подтвердить, что он хотел бы предоставить вам доступ, и вы получите код подтверждения. Сайт провайдера может либо перезвонить вам через URL-адрес, предоставляющий верификатор, либо предоставить пользователю код верификатора, который вам нужен. 3. с оригинальным токеном и верификатором вы можете получить свой последний токен у поставщика. – ldx