我想知道在桌面应用程序中对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_url
从google_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。
我也想知道,在哪里,如何多长时间,当用户启动应用程序我应该存储访问令牌和/或请求令牌,以便用户不会每次总是又问又一遍。
用户授权 - 究竟会那样子喜欢?如果令牌被授权,我是否会打开外部浏览器并频繁地重新检查?在示例代码中,我并不真正看到网页浏览器的打开位置。 – Albert 2011-02-10 12:51:05