扩展 Spring Social 的服务提供商框架
上周,我向您介绍了 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 参数”标题下),我们看到了关于客户端密钥、随机数和时间戳的提及。这些都不是 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 上发送,而不是在请求令牌请求中发送。- 没有验证器的概念,并且不需要将
oauth_verifier参数发送到访问令牌 URL。
对于 OAuth 1.0a,请留意以下迹象:
oauth_callback参数在请求令牌请求中发送,而不是在授权 URL 中发送。- 在回调中从提供商那里收到验证器,并且需要将
oauth_verifier参数发送到访问令牌 URL。
通过在 Netflix 文档中寻找这些线索,我们确定 Netflix 使用的是 OAuth 1.0(而不是 1.0a)。这个信息很重要,在我们定义服务提供商实现时会很有用。
最后,我们需要知道请求令牌、授权和访问令牌的 URL 是什么。页面再往下(在“发起受保护调用”标题下),您会找到细节,告知我们所需的 URL 如下:
- 请求令牌 URL: http://api.netflix.com/oauth/request_token
- 授权 URL: https://api-user.netflix.com/oauth/login
- 访问令牌 URL: http://api.netflix.com/oauth/access_token
请特别注意请求令牌和访问令牌 URL 中使用的协议。大多数提供商在这方面很灵活,建议您使用 HTTPS。然而,根据我与 Netflix 打交道的经验,我发现如果您通过 HTTPS 请求请求令牌或访问令牌,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…