Google Data API:如何对桌面应用程序进行身份验证

Alb*_*ert 8 python gdata-api gdata

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

仔细阅读了文档,似乎我的选项是ClientLogin或OAuth.

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

OAuth似乎是更好的解决方案.但是,似乎缺少一些代码和/或我发现的大多数代码似乎只与Web应用程序相关.Esp.,我按照文档进入了这里.已经在介绍中,它谈到了Web应用程序.然后,我需要指定一个对桌面应用程序没有意义的回调URL.此外,我想知道我应该放置哪些消费者密钥/秘密,因为这对于桌面应用程序也没有意义(特别是对于开源应用程序而言).我搜索了一下,据说这里(在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)
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用.我收到此错误:

抱歉,您已到达未使用Google Apps的域的登录页面.请检查网址,然后重试.

我不太明白.我当然不使用Google Apps.


啊,那个错误来自google_apps_domain=Nonegenerate_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
Run Code Online (Sandbox Code Playgroud)

这将打开Goog​​le OAuth页面,其底部提示:

本网站尚未向Google注册以建立授权请求的安全连接.除非您信任该网站,否则我们建议您拒绝访问.

但它仍然不起作用.当我尝试访问联系人(即只是一个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>
Run Code Online (Sandbox Code Playgroud)

好吧,似乎我确实设置了错误的范围.当我使用http而不是https(ie 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上.


我也想知道,我应该在何处,如何以及在多长时间内存储访问令牌和/或请求令牌,这样每次用户启动应用程序时都不会一次又一次地询问用户.

ldx*_*ldx 2

OAuth 也可以在桌面应用程序中使用。消费者密钥和秘密“匿名”非常适合此类应用程序。

用户不会验证自己的身份。您将从提供商 (Google) 获得一个令牌,然后用户将授权该令牌作为受信任的消费者(您的应用程序)的令牌,通过该令牌可以访问和使用他们的 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。