上周,我向您介绍了 Spring Social 的服务提供者“连接”框架,并展示了它如何简化用户本地应用程序账户与软件即服务 (SaaS) 提供商账户之间的连接创建。今天,我想向您展示如何扩展该服务提供者框架,以处理与 Spring Social 不直接支持的提供商的连接。
为 Netflix 扩展 Spring Social
假设您正在开发一个电影评论网站,用户可以在其中阅读和发布简短的电影评论。通常,电影评论会按最新发布顺序显示在主页上。但是,如果用户将其账户与 Netflix 账户连接,您就可以向他们显示其 Netflix 光盘队列中的电影评论。要实现这一点,您希望利用 Spring Social 的服务提供者框架来连接用户账户与他们的 Netflix 账户。Spring Social 1.0.0.M2 不包含 Netflix 服务提供者或 API 绑定,但可以轻松扩展以支持不直接支持的提供商。
在本文中,我将向您展示如何基于 Spring Social 的服务提供者框架构建,以实现与 Netflix 的连接。我们将首先开发一个 Netflix 服务提供者实现,然后构建一个简单的 API 绑定来满足我们应用程序的需求。开发 Netflix 服务提供者所使用的技术可以应用于扩展 Spring Social 以支持几乎所有服务提供商。您可以通过查阅 GitHub 上的示例代码 来跟着操作。
了解 Netflix 的授权 API
在我们开始开发 Netflix 服务提供者实现之前,我们需要做一些前期研究,了解 Netflix 授权 API 如何工作的一些基本细节。
我们需要确定的第一件事是 Netflix 使用什么授权协议。Netflix API 文档的 认证概览 部分告诉我们他们使用 OAuth,但没有明确说明使用的是 OAuth 规范的哪个版本。因此,需要做一些侦探工作。
在该页下方(在“那些烦人的 OAuth 参数”标题下),我们看到了对 consumer keys、nonces 和 timestamps 的提及。这些内容不适用于 OAuth 2,所以 Netflix 肯定是一个 OAuth 1 提供商。此外,描述中 oauth_version
参数被设置为“1.0”进一步证实了 Netflix 实现了 OAuth 1。
现在我们知道 Netflix 使用 OAuth 1。但同样重要的是要知道他们实现的是规范的 1.0 版本还是 1.0a 版本。服务提供商通常不会在文档中明确说明这一点,而且在任何情况下 oauth_version
的值都应该是“1.0”。然而,有一些明显的迹象可以指出 OAuth 规范的特定版本。这里有一些线索表明使用的是 OAuth 1.0:
oauth_callback
参数发送在授权 URL 上,而不是请求 token 请求中。
- 没有验证器(verifiers)的概念,也无需将
oauth_verifier
参数发送到访问 token URL。
对于 OAuth 1.0a,注意以下迹象:
oauth_callback
参数发送在请求 token 请求中,而不是授权 URL 中。
- 在回调中从提供商处接收到验证器(verifier),并且必须将
oauth_verifier
参数发送到访问 token URL。
根据 Netflix 文档中的这些线索,我们确定 Netflix 使用的是 OAuth 1.0(而不是 1.0a)。这一信息非常重要,在我们定义服务提供者实现时会很有用。
最后,我们需要知道请求 token、授权和访问 token 的 URL 是什么。在该页下方(在“发起受保护调用”标题下),您会找到详细信息,告诉我们所需的 URL 如下:
- 请求 Token URL: http://api.netflix.com/oauth/request_token
- 授权 URL: https://api-user.netflix.com/oauth/login
- 访问 Token URL: http://api.netflix.com/oauth/access_token
特别注意请求 token 和访问 token URL 中使用的协议。大多数提供商在这方面都很灵活,建议使用 https。然而,根据我与 Netflix 的经验,我发现如果您通过 https 请求 request 或 access token,Netflix 会抱怨请求签名无效。不过,授权 URL 通过 https 运行良好。
开发 Netflix 服务提供者实现
要创建一个新的服务提供者实现,我们需要继承 AbstractOAuth1ServiceProvider
或 AbstractOAuth2ServiceProvider
。这两类分别提供了 OAuth 1.0/1.0a 和 OAuth 2 的 OAuth 版本特定基础功能。由于 Netflix 是一个 OAuth 1.0 提供商,我们的 NetFlixServiceProvider
需要继承 AbstractOAuth1ServiceProvider
。
package org.springframework.social.movies.netflix;
import org.springframework.social.connect.oauth1.AbstractOAuth1ServiceProvider;
import org.springframework.social.connect.support.ConnectionRepository;
import org.springframework.social.oauth1.OAuth1Template;
public final class NetFlixServiceProvider extends AbstractOAuth1ServiceProvider<NetFlixApi> {
public NetFlixServiceProvider(String consumerKey, String consumerSecret, ConnectionRepository connectionRepository) {
super("netflix", connectionRepository, consumerKey, consumerSecret,
new OAuth…