上周,我向您介绍了 Spring Social 的服务提供商“连接”框架,并向您展示了它如何简化用户本地应用程序帐户与其在软件即服务 (SaaS) 提供商上的帐户之间建立连接的过程。今天,我想向您展示如何扩展服务提供商框架来处理与 Spring Social 不直接支持的提供商的连接。
扩展 Spring Social 以支持 Netflix
假设您正在开发一个电影评论网站,用户可以在该网站上阅读和发布简短的电影评论。通常,电影评论会按最新条目显示在主页上。但是,如果用户将其帐户连接到其 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…