2011-02-09 58 views
7

我想知道在桌面应用程序中对Google Data API用户进行身份验证的最佳/最简单的方法。Google Data API:如何对桌面应用程序进行身份验证

我通过docs阅读,似乎我的选项是ClientLogin或OAuth。

对于ClientLogin,我似乎必须自己实现用户界面的登录名/密码(以及相关的东西,比如保存在某处等)。我真的不知道是否有更多的支持,可能会弹出一些默认的登录/密码屏幕,并使用操作系统钥匙串来存储密码等。我想知道为什么这种支持不存在?这不是标准程序吗?通过将这个实现留给开发者(当然,将这个impl留给开发者的可能性当然是好的),我猜测很多人在这里提出了非常难看的解决方案(当他们只是想把一个小脚本)。

OAuth似乎是更好的解决方案。但是,似乎有一些代码丢失和/或我发现的大多数代码似乎只与Web应用程序有关。特别是,我遵循了文档并得到了here。在介绍中已经介绍了Web应用程序。之后,我需要指定一个回调URL,这对于桌面应用程序来说没有意义。我还想知道我应该放置什么样的消费者密钥/秘密,因为这对于桌面应用程序来说也没有意义(尤其是对于开源应用程序而言)。我搜索了一下,据说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。


嗯,generate_authorization_urlgoogle_apps_domain=None传来了错误。离那远(即刚好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 

这将在底部的提示打开谷歌的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。我想知道我该怎么做。


此外,该解决方案的另一个问题:

在我的谷歌帐户授权访问的名单,我现在有一堆这样的本地主机条目:

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服务。

下面是OAuth的一个良好的Python库:

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 2011-02-10 12:51:05

相关问题