2011-02-09 3 views
7

Интересно, лучший или простой способ аутентификации пользователя 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.


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

ответ

2

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.

+0

Разрешение пользователем - как именно бы это выглядело как? Открывать внешний веб-браузер и как-то перепроверять часто, если токен разрешен? В примере кода я действительно не вижу, где открыт веб-браузер. – Albert

+0

Кроме того, похоже, что gdata lib уже поставляется с функциями для OAuth. Так что, я думаю, для этого мне не нужна другая библиотека? Или что делает python-oauth2 в дополнение к тому, что у меня уже есть с gdata? – Albert

+0

Трехсторонний OAuth работает следующим образом: 1. Вы запрашиваете токен и токен от поставщика (Google) 2.Вы открываете веб-браузер для пользователя и отправляете его на URL-адрес авторизации провайдера, где пользователь может подтвердить, что он хотел бы предоставить вам доступ, и вы получите код подтверждения. Сайт провайдера может либо перезвонить вам через URL-адрес, предоставляющий верификатор, либо предоставить пользователю код верификатора, который вам нужен. 3. с оригинальным токеном и верификатором вы можете получить свой последний токен у поставщика. – ldx