构建支持 OAuth 的桌面 Twitter 客户端

红薯 发布于 2010/04/09 22:47
阅读 1K+
收藏 1

简介: OAuth 是一种开放的协议,支持用户在不同的 Web 站点之间共享其受保护的资源,而无需担心泄漏的风险。OAuth 是混搭当今的社会网络 Web 站点(比如 Twitter)的理想选择。本系列文章的第一部分将介绍 OAuth,以及开发支持 OAuth 的桌面 Twitter 客户端的示例。本系列文章的第二部分将演示如何开发支持 OAuth 的 Web Twitter 客户端。支持 OAuth 的 Web Twitter 客户端将被迁移到 Google App Engine (GAE) 中,此内容将在本系列文章的第三部分(也是最后一部分)进行介绍。

社会网络被世界各地的人们广泛采用。越来越多的人正在使用 Facebook 和 Twitter 等 Web 站点,但不幸的是,这些 Web 站点就像是分散在浩瀚大海中的孤岛一样,它们之间很难进行通信。尽管许多站点提供了 API 来公开一些数据,但是混搭站点无法扩展以聚集此类 Web 站点。例如,为了提供更好的用户体验,需要管理不同 Web 站点的用户帐户,还需要某种程度的单点登录。用户可能会不愿意将自己的密码提供给第三方 Web 站点。

本系列文章介绍 OAuth,OAuth 是一种开放的协议,支持用户在不同的 Web 站点共享其私有数据和凭证,但仅在拥有数据的原始 Web 站点公开数据。第一篇文章介绍 OAuth,以及支持用户使用 OAuth 更新其 Twitter 状态的桌面应用程序示例。本系列文章的第 2 部分将演示如何开发更实用的、支持 OAuth 的 Twitter Web 客户端。最后一篇文章展示如何将第 2 部分开发的 Web 应用程序部署到 Google App Engine (GAE) 中。

要理解此文章,您应该熟悉使用 Java™ Servlet/JSP 进行 Web 开发。Apache Tomcat 已经被选择用作 Web 容器,并且所有开发工作都已经使用 Eclipse 完成。但是,您应该能够改编本文提供的信息以使其适应您喜欢的工具。注意,编译源代码需要 JDK 5+。

OAuth 简介

OAuth 协议支持用户将存储在一个 Web 站点的私有资源与其他站点共享,而不会将用户的凭证 — 例如,用户名和密码 — 泄漏给除拥有用户数据的 Web 站点之外的其他站点。采用 OAuth 作为其中一种身份验证协议的 Web 站点将增强用户的隐私保护和安全性。在 OAuth 中有 3 个主要角色:用户使用者服务提供商。典型的 OAuth 场景如下所述。

Web 站点 PHOTO(服务提供商)拥有用户(用户)的一些私人照片, 但是此站点不提供打印服务。因此当用户想要打印自己的照片时,他/她可能要转到 Web 站点 PRINTER(使用者), 此站点提供打印服务。但是 Web 站点 PRINTER 没有用户的照片,所以 Web 站点 PHOTO 和 PRINTER 之间肯定会存在数据流。此时就需要用到 OAuth 了。如果站点 PHOTO 支持使用 OAuth 进行身份验证,那么当用户想要打印(存储在站点 PHOTO 上的)照片时,站点 PRINTER 会将用户重定向到站点 PHOTO 以授予其访问照片的权限。此时用户可能会使用常规用户名 - 密码对进行身份验证。当站点 PHOTO 对用户进行了身份验证后,他/她可能会提示授权站点 PRINTER 读取照片。(可能会预设了许可权限以便跳过此步骤。)完成此步骤后,用户将被重定向到站点 PRINTER。现在站点 PRINTER 就拥有了从站点 PHOTO 读取照片的许可权限,并且能够按需打印用户的照片。在所有步骤中,站点 PRINTER 并不知道用户登录站点 PHOTO 的凭证。这样就很好地保护了用户的隐私。图 1 以一个简单的顺序流程图阐明了上述流程。


图 1. 用户、使用者和服务提供商之间的 OAuth 交互
展示了用户、使用者和服务提供商之间的交互的图(12 个步骤)。

(单击查看 此 图的详细介绍。)

OAuth Core 1.0 在 2007 年末才定稿。编写此文章时,最新版本是 1.0a,在这个版本中修正了一个安全性问题,此问题与针对 OAuth 请求令牌批准流程的会话固定攻击有关。如今 OAuth 已被 Google 和 Yahoo 等主要互联网公司所采用。

Twitter 桌面客户端的开发

作为最成功的社会网络示例之一,Twitter 已吸引了大量用户。不仅仅是个人,现在公司也使用 Twitter 快速更新他们的状态。例如,IBM developerWorks 正在使用 Twitter 告知人们网站的最新内容。Twitter 支持 OAuth,这一点儿也不奇怪,此文章将会阐述这一点。首先我会介绍如何使用 OAuth 开发简单的 Twitter 桌面客户端。如果您还没有 Twitter 帐户,在继续阅读此文章之前,请在 http://twitter.com 上注册一个帐户。

在 Twitter 上注册您的桌面应用程序:MyTtDesktopClient

目前 Twitter 支持两种类型的身份验证:Basic AuthOAuth。尽管 Basic Auth 使用起来很简单,但是在 HTTP 传输过程中用户名和密码不受保护,所以此文章中不予讨论。在您可以将 OAuth 和 Twitter 结合使用之前,首先需要在 http://twitter.com/oauth_clients 上注册您的应用程序。注册应用程序时我提供了以下信息。

  • Application Name:MyTtDesktopClient
  • Description:使用 OAuth 的桌面 Twitter 客户端
  • Application Website:在此处输入您的应用程序主页
  • Application Type:客户端 - 我们将要开发桌面客户端
  • Default Access type:读 & 写 - 我们想要授予用户写入权限
  • Use Twitter for login:否 - 我们不打算使用 Twitter 进行身份验证

注意,您应该将应用程序类型选择为 Client 而不是 Browser。(在本系列的第 2 部分,我将介绍基于 Web 的示例。)此外,切记授予读 & 写权限,否则您的应用程序将只能从 Twitter 读取内容。

注册成功后,您将获得一个使用者密钥、使用者机密(secret)和 3 个 URL(请求令牌 URL、访问令牌 URL 和授权 URL)。现在就可以开始实际使用了。

开发和测试 MyTtDesktopClient

我将使用 Twitter4J,它是 TwitterAPI 的一个开源 Java 库(参见 参 考资料)。Twitter4J 封装了许多函数,所以我们可以关注逻辑,无需接触 Twitter 的低级别 API 调用。Twitter4J 的另一个好处是它支持 OAuth,这将明显减少我们的开发工作。我们将从 清 单 1 中的类 myttdesktopclient.OAuthTwitterClientupdateStatus(String status) 方法开始。 源代码可从下面的 下 载 部分获得。不要忘记将使用者密钥和机密(记住,当注册客户端时,Twitter 会提供这些参数)放在 OAuthTwitterClient.java 的内部。


清单 1. 类 myttdesktopclient.OAuthTwitterClientupdateStatus(String status) 方法

				
public void updateStatus(String status) throws TwitterException, IOException {
Twitter twitter = new Twitter();
twitter.setOAuthConsumer(consumerKey, consumerSecret);
RequestToken requestToken = twitter.getOAuthRequestToken();
AccessToken accessToken = null;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while (accessToken == null) {
System.out.println("Open the following URL and grant access to
your account:");
System.out.println(requestToken.getAuthorizationURL());
// Copy the authorisation URL in your browser
// http://twitter.com/oauth/authorize?oauth_token=xxxxxxxxxxxxxxxxxxxxxxxx
// Log in Twitter, grant access
// Get a PIN returned, e.g., 738805
// Notice you can use HttpClient to do the job above
System.out.println("Copy the PIN displayed in your browser, then
hit ENTER: ");
String pin = br.readLine();
accessToken = twitter.getOAuthAccessToken(requestToken, pin);
}

// Persist the access token for future reference
int userId = twitter.verifyCredentials().getId();
storeAccessToken(userId, accessToken);
Status twitterStatus = twitter.updateStatus(status);
System.out.println("Successfully updated the status for user with ID "
+ userId + " to [" + twitterStatus.getText() + "].");
}

 

updateStatus(String status) 方法首先构造一个 Twitter 对象,然后设置使用者密钥和机密。这样就会从 Twitter 获得一个请求令牌。然后该方法会为用户打印出 URL,以授予用户访问存储在 Twitter 上的数据的权限。现在在浏览器中复制并粘贴代码输出的 URL,并单击 Enter 键,您将会被要求授权 MyTtDesktopClient 的请求(参见 图 2)。注意,此时您将在 Twitter 的站点进行授权,而且我们的桌面客户端不了解授权是如何执行的。


图 2. 授予对 MyTtDesktopClient 的访问权
请求授予对 MyTtDesktopClient 的访问权的 Twitter  屏幕截图,在空白处输入用户名和密码,并带有 Deny 和 Allow 按钮。

如果您授权了请求,Twitter 将返回一个 PIN,如 图 3 所示。


图 3. Twitter 返回了访问 MyTtDesktopClient 的一个 PIN
显示 Twitter 返回访问 MyTtDesktopClient 的 PIN 的屏幕截图,该 PIN 是一个 7  位数字。

现在将 PIN 复制并粘贴到运行代码的终端中并单击 Enter 键,您应看到类似 清 单 2 的输出。如 清 单 1 所示,桌面客户端仅关注授权流程的输出。如果成功了(在这种情况下,Twitter 返回了 PIN),就会获得一个访问令牌,客户端可使用此访问令牌代表用户更新 Twitter 状态。这是 OAuth 的密钥,并且用户的机密(用户名和密码)不会泄漏给 MyTtDesktopClient。如果您登录到 Twitter,就会看到自己的最新更新 “Studying OAuth”(参见 图 4)。注意,最新状态下面的消息表明它是被 MyTtDesktopClient 更新的。


清单 2. MyTtDesktopClient 的输出

				
Open the following URL and grant access to your account:
http://twitter.com/oauth/authorize?oauth_token=matzsp0Q8k5GfhX2DQoQaHEipBH3g3ieqzPg5QyYek
Copy the PIN displayed in your browser, then hit ENTER:
1944867
Storing access token for 23741179...Done
Successfully updated the status for user with ID 23741179 to [Studying OAuth].



图 4. 由 MyTtDesktopClient 更新的 Twitter 状态
显示由 MyTtDesktopClient 更新的 Twitter 状态的屏幕截图

注意,在 清 单 1 中,在更新 Twitter 状态之前,通过调用 storeAccessToken 方法存储了访问令牌。这是因为目前 Twitter 的访问令牌还没有到期。所以在用户返回并使用我们的客户端时无需再次授权访问。这样就改善了用户体验。在本例中,用户的访问令牌以纯文本文件的形式存储, 它还可以在将来重用。看一下源代码(可在 下 载 部分获得)中的 storeAccessTokenloadAccessToken 方法。名为 updateStatus(int userId, String status) 的新更新方法使用了存储的访问令牌(参见 清 单 3)。在 main 方法中,为行 tt.updateStatus("Studying OAuth"); 添加注释,并取消行 tt.updateStatus(23741179, "Studying OAuth again"); 的注释。使用您自己的 Twitter ID 替换 23741179。 重新编译并运行代码,您就会发现,现在无需执行上述授权流程就可以更新自己的 Twitter 状态。

清单 3. 类 myttdesktopclient.OAuthTwitterClientupdateStatus(int userId, String status) 方法

public void updateStatus(int userId, String status)
throws TwitterException, IOException {
Twitter twitter = new Twitter();
twitter.setOAuthConsumer(consumerKey, consumerSecret);
AccessToken accessToken = loadAccessToken(userId);
twitter.setOAuthAccessToken(accessToken);
Status twitterStatus = twitter.updateStatus(status);
System.out.println("Successfully updated the status for user with ID "
+ userId + " to [" + twitterStatus.getText() + "].");
}

 

结束语

在本系列的第一篇文章中,我介绍了 OAuth 协议。通过示例应用程序 MyTtDesktopClient, 我们了解了使用 OAuth 的基本元素。这里的特别之处在于用户的服务提供商凭证(Twitter 用户名和密码)不会泄漏给使用者 MyTtDesktopClient。 在本系列的第 2 部分,我将演示如何开发更实用的 Web 应用程序,以支持用户通过 OAuth 与 Twitter 进行通信。

下载本文源码

加载中
返回顶部
顶部