介绍 Spring Social 的服务提供商框架

工程 | Craig Walls | 2011 年 3 月 2 日 | ...

在我之前的帖子中,我向您介绍了 Spring Social 到流行的软件即服务 (SaaS) API(如 Twitter、Facebook、LinkedIn 和 TripIt)的 Java 绑定。除了提供常见 API 操作的简单、强类型的 Java 方法外,这些绑定还可以确保每个 HTTP 请求都包含必要的凭据,以便授权您的应用程序代表用户调用 API。

我的第一个帖子没有解决的问题是:我们如何管理代表用户调用服务 API 所需的凭据? 我很高兴地告诉大家,我们现在有了这些问题的答案。

本周早些时候,我们宣布了 Spring Social 项目第二个里程碑版本的发布。Spring Social 1.0.0.M2 中最重要的新功能是引入了服务提供商“连接”框架。今天,我想向您介绍这个框架,并向您展示如何使用它来管理与 SaaS 提供商的“连接”。

本文中的示例来自 Spring Social Showcase。要进行跟随,请克隆存储库并按照 README 构建和部署示例应用程序。

获取 Spring Social

随着 M2 版本的发布,Spring Social 已被拆分为多个模块

  • spring-social-core - 服务提供商框架、OAuth 支持和核心类。
  • spring-social-web - 连接控制器和支持类型。
  • spring-social-facebook - 用于连接 Facebook 和支持通过 Facebook 登录应用程序的服务提供商实现。
  • spring-social-twitter - 用于连接 Twitter 和支持通过 Twitter 登录应用程序的服务提供商实现。
  • spring-social-linkedin - 用于连接 LinkedIn 的服务提供商实现。
  • spring-social-tripit - 用于连接 TripIt 的服务提供商实现。
  • spring-social-github - 用于连接 GitHub 的服务提供商实现。
  • spring-social-gowalla - 用于连接 Gowalla 的服务提供商实现。
  • spring-social-test - 支持测试服务提供商实现和 API 绑定。

根据您的需求,您不一定需要所有这些模块。最少,您需要核心模块。您可以将其添加到 Maven 构建的项目中,如下所示:


<dependency>
    <groupId>org.springframework.social</groupId>
    <artifactId>spring-social-core</artifactId>
    <version>1.0.0.M2</version>
</dependency>

在您可能在 Web 应用程序中使用 Spring Social 的情况下,您还需要 Web 模块


<dependency>
    <groupId>org.springframework.social</groupId>
    <artifactId>spring-social-web</artifactId>
    <version>1.0.0.M2</version>
</dependency>

然后,您需要添加一个或多个提供商模块。在我们的示例中,我们将讨论将 Twitter 连接添加到应用程序,因此我们需要 twitter 模块


<dependency>
    <groupId>org.springframework.social</groupId>
    <artifactId>spring-social-twitter</artifactId>
    <version>1.0.0.M2</version>
</dependency>

由于我们正在基于 Spring Social 的预览版本进行开发,因此我们需要将 Spring 的预览存储库添加到 pom.xml 文件中


<repository>
	<id>org.springframework.maven.milestone</id>
	<name>Spring Maven Milestone Repository</name>
	<url>http://maven.springframework.org/milestone</url>
	<snapshots><enabled>false</enabled></snapshots>
</repository>

请注意,虽然 Spring Social 1.0.0.M2 对 Spring Framework 3.1 有编译时依赖,但 Spring Social 与 Spring Framework 3.0.x 配合使用效果也很好。

解决了构建中的依赖关系后,我们就可以为应用程序添加 Twitter 连接功能了。

连接 Twitter

为了帮助理解 Spring Social 的服务提供商“连接”框架能带来什么,让我们快速浏览一下示例应用程序。

登录示例应用程序后,您首先会看到一个列表,其中列出了示例应用程序支持连接的服务提供商:Twitter、Facebook 和 TripIt。它们应该都显示您的账户尚未与其中任何一个连接。

如果您点击 Twitter 链接,您将被重定向到一个连接状态页面,并有机会“连接到 Twitter”。您还会看到一个复选框,如果勾选,将在连接到 Twitter 后发布一条关于 Spring Social Showcase 的推文。

点击“连接到 Twitter”按钮后(是否勾选“发布推文…”复选框由您决定),您将被重定向到 Twitter 的授权页面,该页面应该看起来像这样:

如果您已登录 Twitter,则不会显示用户名和密码字段。但无论哪种情况,您都有机会拒绝或允许示例应用程序访问和更新您在 Twitter 上的数据。当您点击“允许”按钮授予权限时,Twitter 将重定向回示例应用程序,并在示例账户和您的 Twitter 个人资料之间创建一个连接。您将看到一个连接状态页面,这次会表明存在一个连接。

此时,您可以选择与 Twitter 断开连接(如果您愿意)。但目前,请返回主页,您会看到您已连接到 Twitter。

如果您点击“Twitter”链接,并且存在一个可用连接,您将被带到 Twitter Showcase 页面,该页面显示了您的个人资料图片、Twitter 显示名称和 Twitter 屏幕名称等内容。您还可以选择从这里连接另一个 Twitter 账户(您可以将多个提供商账户连接到一个应用程序账户),断开与 Twitter 的连接,或发布一条推文。

服务提供商“连接”框架

当您第一次点击示例应用程序中的“Twitter”链接时,您看到的是 Twitter 的连接状态页面。该页面由 Spring Social 的 ConnectController 提供服务。ConnectController 是一个 Spring MVC 控制器,负责处理授权过程。对于 Twitter,这是一个 OAuth 1 授权流程。对于 OAuth 1,ConnectController 支持以下流程:

  • GET /connect/{provider ID} - 显示连接状态页面。
  • POST /connect/{provider ID} - 启动连接流程,从提供商请求一个请求令牌,然后重定向到提供商的授权页面。
  • GET /connect/{provider ID}?oauth_token={request token}&oauth_verifier={verifier} - 处理授权后的回调,用请求令牌和验证器交换一个访问令牌,并创建连接。
  • DELETE /connect/{provider ID} - 断开与提供商的连接。

ConnectController 还支持 OAuth 2 的授权流程。当授权针对像 Facebook 这样的基于 OAuth 2 的提供商时,ConnectController 的流程略有不同:

  • GET /connect/{provider ID} - 显示连接状态页面。
  • POST /connect/{provider ID} - 启动与提供商的授权,重定向到提供商的登录和/或授权页面。
  • GET /connect/{provider ID}?code={code} - 处理来自提供商的授权回调,用代码交换访问令牌,并创建连接。
  • DELETE /connect/{provider ID} - 断开与提供商的连接。

ConnectController 可以通过简单地添加以下 <bean> 元素来配置到 Spring MVC 应用程序中。


<bean class="org.springframework.social.web.connect.ConnectController">
    <constructor-arg value="${application.url}" />
</bean>

如果您查看示例应用程序中 ConnectController 的配置方式,您会发现它有一个 interceptors 属性,注入了一个拦截器 bean 列表。连接拦截器允许您将自定义功能注入到连接流程中。其中一个拦截器 TweetAfterConnectInterceptor 负责在您连接到 Twitter 后发布一条推文。(有关连接拦截器的更多信息,请参阅 参考文档。)

当请求发送到 ConnectController 时,它会与服务提供商类协同工作,以处理与服务的后台交互。对于 Twitter,该提供商类是 TwitterServiceProvider,并在 Spring 中配置如下:


<bean class="org.springframework.social.twitter.connect.TwitterServiceProvider">
    <constructor-arg value="${twitter.appId}" />
    <constructor-arg value="${twitter.appSecret}" />
    <constructor-arg ref="connectionRepository" />
</bean>

TwitterServiceProvider,像 Spring 的所有服务提供商实现一样,使用以下参数构建:

  • 应用程序的 ID 或消费者密钥。
  • 应用程序的密钥或消费者密钥。
  • 一个用于持久化连接详细信息的连接存储库 bean 的引用。

当您在服务提供商处注册应用程序时,您会获得应用程序的消费者密钥和密钥。要注册一个应用程序到 Twitter,请访问 https://dev.twitter.com/apps/new 并填写表单。完成后,Twitter 将返回一个显示您的应用程序详细信息的页面,包括消费者密钥和消费者密钥。

在这种情况下,应用程序的 Twitter 应用程序 ID 和密钥被表示为占位符变量,由属性占位符配置器解析。建议您将这些详细信息外部化,因为您在生产部署中很可能使用与测试和开发环境不同的 ID/密钥对。

Spring 的每个服务提供商类都有一个提供商 ID(从其 getId() 方法返回,并且不同于其 Spring bean ID)。ConnectController 将使用该 ID,如 URL 路径中指定的那样,在创建连接时选择它将与之合作的服务提供商。对于 TwitterServiceProvider,提供商 ID 是“twitter”。将此 ID 映射到 ConnectController 的请求映射,我们得到以下流程:

  • GET /connect/twitter - 显示用户与 Twitter 的连接状态。
  • POST /connect/twitter - 从 Twitter 获取一个请求令牌,然后重定向到 Twitter 的授权页面。当您点击“连接到 Twitter”按钮时,流程就是到这里。
  • GET /connect/twitter?oauth_token={request token}&oauth_verifier={verifier} - 处理授权后的回调,用请求令牌和验证器交换一个访问令牌,并创建连接。
  • DELETE /connect/twitter - 断开与 Twitter 的连接。当您点击“断开连接”按钮时,就会发生这种情况。

建立连接后,将其存储起来供将来使用非常重要,这样您就不必反复要求用户重新授权您的应用程序。因此,TwitterServiceProvider 依赖于连接存储库来持久化连接信息。Spring Social 提供了 JdbcConnectionRepository,它将连接详细信息持久化到关系数据库中。JdbcConnectionRepository bean 的配置如下:


<bean id="connectionRepository" class="org.springframework.social.connect.jdbc.JdbcConnectionRepository">
    <constructor-arg ref="dataSource" />
    <constructor-arg ref="textEncryptor" />
</bean>

JdbcConnectionRepository 依赖于一个数据源,通过该数据源它将访问数据库,以及一个 Spring Security 3.1 的 TextEncryptor 接口实例。它使用文本加密器在将连接凭据(例如访问令牌和密钥)存储到数据库时对其进行加密。作为一个示例应用程序,Spring Security 的加密需求相对较少,因此它与一个无操作文本加密器连接。


<bean id="textEncryptor" class="org.springframework.security.crypto.encrypt.Encryptors" 
      factory-method="noOpText" />

(对于生产级别的加密,请考虑 Spring Security 的 Encryptors 静态工厂类提供的其他加密器。)

处理连接

当您首次登录 Spring Social Showcase 时,它会显示一个服务提供商列表,并表明您与其中任何一个都没有连接。在与 Twitter 完成连接过程并返回到该页面后,它会显示已建立连接。

示例应用程序的 HomeController 通过调用每个提供商的 isConnected() 方法来确定与每个提供商的连接状态。


for (ServiceProvider<?> serviceProvider : serviceProviders) {
	boolean connected = serviceProvider.isConnected(currentUser.getName());
	model.addAttribute(serviceProvider.getId() + "_status", connected ? "Yes" : "No");
}

如果给定账户与服务提供商之间存在一个或多个连接,isConnected() 方法将返回 true。

您还可以通过调用提供商的 getConnections() 方法来请求连接列表。


List<ServiceProviderConnection<TwitterApi>> connections = twitterProvider.getConnections(currentUser.getName());

从这些连接中的任何一个,您都可以检索服务 API。例如,从第一个连接获取 TwitterApi 的一个实例:


TwitterApi twitter = connections.get(0).getServiceApi();

使用该 TwitterApi 对象,您可以与 Twitter 进行交互,获取时间线条目、发布推文或执行 TwitterApi 接口中定义的任何其他操作。

这里需要注意的关键一点是,应用程序代码在任何时候都不需要直接处理访问令牌和密钥即可与服务进行交互。服务提供商框架在幕后处理这些细节。

总结

Spring Social 1.0.0.M2 提供了一个服务提供商框架,大大简化了应用程序在代表用户获取访问服务的授权以及将用户本地应用程序账户与他们在提供商处的账户连接方面的作用。为 Spring 应用程序添加连接功能涉及将服务提供商配置为 Spring 应用程序上下文中的一个 bean,并配置 Spring Social 的 ConnectController 来处理授权过程。有关使用 Spring Social 服务提供商框架的更多信息,请参阅 参考文档

虽然 Spring Social 1.0.0.M2 只为 6 个提供商(Facebook、Twitter、LinkedIn、TripIt、GitHub 和 Gowalla)提供了服务提供商实现,但该框架易于扩展。在后续文章中,我将展示编写自定义服务提供商实现所需的知识,使您能够将 Spring Social 的连接支持用于您需要连接的任何提供商。

一如既往,我们非常乐意听取您的反馈。我们鼓励您在 论坛 中与我们合作,或通过提交增强请求到 问题跟踪

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看所有