使用 Spring.NET Social 连接社交网络 API





5.00/5 (2投票s)
Spring.NET Social 帮助您简化与 Facebook 和 Twitter 等软件即服务 (SaaS) 提供商的身份验证 (OAuth) 和 API 绑定。
引言
Spring.NET Social 使添加对框架尚不支持的服务提供商的支持变得容易。
如果您查看现有的客户端项目,例如 Twitter、Dropbox、LinkedIn 和 Facebook,您会发现它们的实现方式一致,并且应用了一组定义明确的扩展点。
在本文中,您将学习如何添加对您希望支持的新服务提供商的支持。
流程概述
添加新服务提供商支持的过程包括几个步骤:
- 为客户端代码创建一个源项目,例如
Spring.Social.Twitter
。 - 开发或集成到提供商 API 的绑定,例如
ITwitter
。 - 创建一个
IServiceProvider
模型,允许用户授权远程提供商并获取已授权的 API 实例,例如TwitterServiceProvider
。
本文的以下部分将通过示例向您介绍每个步骤。
为提供商客户端代码创建源项目
我们建议新社交客户端代码驻留在 Spring.Social.{providerId}
程序集中,其中 {providerId}
是您为添加支持的服务提供商分配的唯一标识符。
在该程序集中,我们建议以下命名空间结构:
命名空间 | 提供商 |
Spring.Social.{providerId}.Api | 定义 API 绑定的公共接口和类型。 |
Spring.Social.{providerId}.Api.Impl | API 绑定的实现。 |
Spring.Social.{providerId}.Connect | 建立与服务提供商连接所需的类型。 |
您可以通过查看 Twitter 项目来了解这种推荐结构的实际应用。
在这里,核心服务 API 类型 ITwitter
位于 Api
命名空间中,与其支持的操作类型和数据传输对象类型一起。
该接口的主要实现 TwitterTemplate
位于 Api.Impl
命名空间中(以及已从该视图中排除的其他内部类型)。
最后,Connect
命名空间包含 IServiceProvider
的实现,这些实现使建立与 Twitter 的连接成为可能。
开发提供商 API 绑定
Spring.NET Social 倾向于开发强类型绑定到外部服务提供商 API。
这为 .NET 应用程序提供了一个简单的、面向域的接口来使用该 API。
设计新的 API 绑定
API 开发人员完全控制其 API 绑定的设计和实现。
即便如此,我们还是提供了一些设计指南,以提高整体一致性和质量:
- 倾向于将 API 绑定接口与其实现分离。
这在上一节的 Twitter 示例中得到了说明。
在那里,“Twitter
”是核心 API 绑定类型,它在Spring.Social.Twitter.Api
命名空间中与其他公共类型一起声明。
TwitterTemplate
是该接口的主要实现,位于Spring.Social.Twitter.Api.Impl
命名空间中,与其他内部实现类型一起。 - 倾向于按 RESTful 资源分层组织 API 绑定。
基于 REST 的 API 通常以分层方式公开对多个资源的访问。
例如,Twitter 的 API 提供了对“状态时间线”、“搜索”、“列表”、“直接消息”、“好友”、“地理位置”和“用户”的访问。ITwitter
接口被分层组织,而不是将所有操作添加到单个扁平的“Twitter
”接口中。
public interface ITwitter : IApiBinding
{
IBlockOperations BlockOperations { get; }
IDirectMessageOperations DirectMessageOperations { get; }
IFriendOperations FriendOperations { get; }
IGeoOperations GeoOperations { get; }
IListOperations ListOperations { get; }
ISearchOperations SearchOperations { get; }
ITimelineOperations TimelineOperations { get; }
IUserOperations UserOperations { get; }
IRestOperations RestOperations { get; }
}
例如,IDirectMessageOperations
包含对 Twitter“直接消息”资源的 API 绑定。
public interface IDirectMessageOperations
{
IList<DirectMessage> GetDirectMessagesReceived();
IList<DirectMessage> GetDirectMessagesReceived(int page, int pageSize);
IList<DirectMessage> GetDirectMessagesReceived(int page, int pageSize, long sinceId, long maxId);
IList<DirectMessage> GetDirectMessagesSent();
IList<DirectMessage> GetDirectMessagesSent(int page, int pageSize);
IList<DirectMessage> GetDirectMessagesSent(int page, int pageSize, long sinceId, long maxId)
DirectMessage GetDirectMessage(long id);
DirectMessage SendDirectMessage(string toScreenName, string text);
DirectMessage SendDirectMessage(long toUserId, string text);
void DeleteDirectMessage(long messageId);
}
实现新的 API 绑定
API 开发人员可以自由地使用他们认为合适的任何 REST/HTTP 客户端来实现其 API 绑定。也就是说,现有的 Spring.NET Social 绑定(如 Twitter)都使用 Spring.NET REST Client Framework 的 RestTemplate
。
RestTemplate
是一个 REST 客户端,可在各种数据交换格式(JSON、XML 等)上提供统一的对象映射接口。
如上一节所述,我们建议将实现类型与公共 API 类型分开。我们还建议将实现细节保持为内部。
API 绑定实现的构造方式将因 API 的授权协议而异。对于使用 OAuth1
保护的 API,构造需要 consumerKey
、consumerSecret
、accessToken
和 accessTokenSecret
。
public TwitterTemplate(string consumerKey, string consumerSecret,
string accessToken, string accessTokenSecret)
{
...
}
对于 OAuth2
,只需要 accessToken
。
public GitHubTemplate(string accessToken)
{
...
}
每次向 API 服务器发出的请求都需要使用绑定构造过程中提供的授权凭据进行签名。
此签名过程包括在执行每个客户端请求之前,向其添加“Authorization
”标头。
对于 OAuth1
,此过程非常复杂,用于支持客户端和服务器之间精心设计的请求签名验证算法。
对于 OAuth2
,它要简单得多,但仍然因 OAuth2
规范的各种草案而异。
为了封装这种复杂性,对于每种授权协议,Spring Social 都提供了一个基类,您可以从中扩展,以构建一个预配置的 RestTemplate
实例,该实例会为您执行请求签名。
对于 OAuth1
:
public class TwitterTemplate : AbstractOAuth1ApiBinding
{
public TwitterTemplate(string consumerKey, string consumerSecret,
string accessToken, string accessTokenSecret)
: base(consumerKey, consumerSecret, accessToken, accessTokenSecret);
{
}
}
对于 OAuth2
:
public class GitHubTemplate : AbstractOAuth2ApiBinding
{
public GitHubTemplate(string accessToken)
: base(accessToken);
{
}
}
配置好后,您只需实现调用 RestTemplate
并实现各种 API 操作。
现有的 Spring.NET Social 客户端模块都以标准方式调用其 RestTemplate
实例。
public TwitterProfile GetUserProfile()
{
return this.RestTemplate.GetForObject<TwitterProfile>("account/verify_credentials.json");
}
有关完整的实现示例,请参阅基于 Spring.NET Social 的现有扩展的源代码。
测试新的 API 绑定
作为 RestTemplate
组件的一部分,Spring.NET REST Client Framework 包括一个用于单元测试 RestTemplate
代码的框架。
该框架包含一个“MockRestServiceServer
”,可用于模拟与远程服务提供商的 API 调用。
这使得能够开发独立、高性能、自动化的单元测试,以验证客户端 API 绑定和对象映射行为。
要使用,请先针对 API 实现使用的 RestTemplate
实例创建 MockRestServiceServer
。
在此示例中,TwitterTemplate
使用 RestTemplate
来消费 Twitter REST API 资源。
TwitterTemplate twitter = new TwitterTemplate("consumerKey", "consumerSecret",
"accessToken", "accessTokenSecret");
MockRestServer mockServer = MockRestServiceServer.CreateServer(twitter.RestTemplate);
然后,对于每个测试用例,记录关于服务器应如何被调用以及应如何响应的期望。
[Test]
public void UpdateStatus()
{
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.ContentType = MediaType.APPLICATION_JSON;
mockServer.ExpectNewRequest()
.AndExpectUri("https://api.twitter.com/1/statuses/update.json")
.AndExpectMethod(HttpMethod.POST)
.AndExpectHeader("Content-Type", "application/x-www-form-urlencoded")
.AndExpectBody("status=Test+Message")
.AndRespondWith(JsonResource("Status"), responseHeaders);
Tweet tweet = twitter.UserOperations.UpdateStatus("Test Message");
Assert.AreEqual(12345, tweet.ID);
Assert.AreEqual("Test Message", tweet.Text);
}
在上例中,响应正文是从位于与测试类相同命名空间下的“Status.json
”嵌入资源文件中写入的。
private IResource JsonResource(string filename)
{
return new AssemblyResource(filename + ".json", typeof(TwitterTemplateTests));
}
文件的内容应镜像远程服务提供商将返回的内容,从而可以完全测试客户端的 JSON 反序列化行为。
{
"id" : 12345,
"text" : "Tweet 1",
...
}
有关完整的测试示例,请参阅基于 Spring.NET Social 的现有扩展的源代码。
创建 ServiceProvider 模型
如上一节所述,安全 API(如 GitHub 或 Twitter)的客户端绑定需要有效的用户授权凭据才能工作。
此类凭据通常通过让您的应用程序与服务提供商进行授权“舞蹈”或握手来获得。
Spring.NET Social 提供了 IServiceProvider<T>
抽象来处理此“授权舞蹈”。该抽象还充当原生 API (T
) 实例的工厂。
由于授权舞蹈是协议特定的,因此存在每个授权协议的 IServiceProvider
特化。
例如,如果您正在连接到基于 OAuth2
的提供商,您将实现 IOAuth2ServiceProvider
。
完成此操作后,您的实现可用于执行 OAuth2
舞蹈并获取已授权的 API 实例。
以下各节描述了每种 ServiceProvider
类型的实现步骤。
OAuth 2
要实现基于 OAuth2
的 ServiceProvider
,请首先创建一个名为 {ProviderId}ServiceProvider
的 AbstractOAuth2ServiceProvider<T>
的子类。
将通用类型 T
参数化为 ServiceProvider
API 的绑定。
定义一个接受 clientId
和 clientSecret
的单一构造函数。
最后,实现 GetApi(string)
来返回一个新的 API 实例。
以 GitHub 和 Facebook 示例作为基于 OAuth2
的服务提供商的示例。
public class GitHubServiceProvider : AbstractOAuth2ServiceProvider<IGitHub>
{
public GitHubServiceProvider(string clientId, string clientSecret)
: base(new OAuth2Template(clientId, clientSecret,
"https://github.com/login/oauth/authorize",
"https://github.com/login/oauth/access_token"))
{
}
public override IGitHub GetApi(string accessToken)
{
return new GitHubTemplate(accessToken);
}
}
在构造函数中,您应该调用基类构造函数,并将配置好的、实现 IOAuth2Operations
的 OAuth2Template
传递上去。OAuth2Template
将处理与提供商的“OAuth
舞蹈”,并应使用提供的 clientId
和 clientSecret
以及特定于提供商的 authorizeUrl
和 accessTokenUrl
进行配置。
一些提供商支持通过与授权 URL 不同的身份验证 URL 进行提供商登录。使用上面的 OAuth2Template
构造函数将假定身份验证 URL 与授权 URL 相同。但是,您可以使用 OAuth2Template
的其他构造函数来指定不同的身份验证 URL。
在 GetApi(string)
中,您应该构造您的 API 实现,并传递使有权访问受保护资源所需的访问令牌。
OAuth 1
要实现基于 OAuth2
的 ServiceProvider
,请首先创建一个名为 {ProviderId}ServiceProvider
的 AbstractOAuth1ServiceProvider<T>
的子类。
将通用类型 T
参数化为 ServiceProvider
API 的绑定。
定义一个接受 consumerKey
和 consumerSecret
的单一构造函数。
最后,实现 GetApi(string, string)
来返回一个新的 API 实例。
以 Twitter 和 LinkedIn 示例作为基于 OAuth1
的服务提供商的示例。
public class TwitterServiceProvider : AbstractOAuth1ServiceProvider<ITwitter>
{
public TwitterServiceProvider(string consumerKey, string consumerSecret)
: base(consumerKey, consumerSecret, new OAuth1Template(consumerKey, consumerSecret,
"https://api.twitter.com/oauth/request_token",
"https://api.twitter.com/oauth/authorize",
"https://api.twitter.com/oauth/authenticate",
"https://api.twitter.com/oauth/access_token"))
{
}
public override ITwitter GetApi(string accessToken, string secret)
{
return new TwitterTemplate(this.ConsumerKey, this.ConsumerSecret, accessToken, secret);
}
}
在构造函数中,您应该调用基类构造函数,并将 consumerKey
、secret
和实现 IOAuth1Operations
的配置好的 OAuth1Template
传递上去。OAuth1Template
将处理与提供商的“OAuth
舞蹈”。
它应使用提供的 consumerKey
和 consumerSecret
以及特定于提供商的 requestTokenUrl
、authorizeUrl
、authenticateUrl
和 accessTokenUrl
进行配置。authenticateUrl
参数是可选的,如果提供商没有与授权 URL 不同的身份验证 URL,则可以省略。
如您在此处所见,OAuth1Template
使用 Twitter 的身份验证 URL(用于提供商登录)进行构造,该 URL 与其授权 URL 不同。
一些提供商没有用于身份验证和授权的单独 URL。
在这些情况下,您可以使用 OAuth1Template
的其他构造函数,该构造函数不接受身份验证 URL 作为参数。
在 GetApi(string, string)
中,您应该构造您的 API 实现,并传递使有权访问受保护资源所需的四个令牌。
结论
查看附加的示例,了解使用 Spring.NET Social 连接和使用网络社交 API 的便捷性。