使用 .NET 的 Twitter OAuth 身份验证






4.79/5 (29投票s)
一个示例,展示了如何使用 oAuth 和应用程序访问令牌验证 Twitter 应用程序的身份。
引言
在本文中,我想演示如何在 .NET 中实现 OAuth 身份验证。我之前写过关于我不喜欢用于社交媒体集成的第三方 SDK,以及我们应该如何利用基于技术的解决方案。其中一个难点是,与实际发出请求相比,实现基于 OAuth 的身份验证相对困难。虽然有可用的文档,但似乎缺少与之配套的 .NET 示例代码。
与我之前文章中的想法一致,我建议使用开源的基于 OAuth 的库来解决这个问题,并再次避免求助于第三方 Twitter/Facebook 实现,因为这些实现会将代码更紧密地耦合到特定的 API。 这使得解决方案更具可重用性,并基于特定技术来更好地对应用程序进行未来验证。
我也之前展示过如何将客户端插件与服务器端代码结合使用,以加快该领域的开发。但是,有时确实需要在服务器端纯粹实现身份验证。
那么这有多难呢?
事实证明,在 .NET 中在服务器端实现 OAuth 并不太难,关键在于获得正确的编码和身份验证签名。 由于示例很少,这可能会让人望而却步,因此这里有一个使用纯 .NET 编写的示例,它使用了官方的 Twitter OAuth 文档和一些反复试验。
背景
以下示例展示了如何使用已注册的 Twitter 应用程序针对 Twitter API 进行身份验证。 以这种方式进行身份验证时,与 API 的任何交互都将表现得像是来自应用程序注册的 Twitter 帐户。 因此,它对于从特定帐户发送状态更新或发送通知非常有用。
通常,OAuth 需要将用户重定向到登录屏幕以获取 oAuth 令牌,这需要更多的工作。 但是,通过 Twitter 应用程序进行身份验证时,将跳过此步骤,因为您的应用程序已经提供了 oAuth 令牌(访问令牌)。 无论您使用的是应用程序 oAuth 令牌还是用户 oAuth 令牌,以下代码都可用于针对 Twitter API 进行身份验证。
代码
第一步是访问 Twitter 开发人员 部分并注册一个新应用程序。 完成后,您将获得一组公共/私有密钥,您需要在下面的示例中替换它们才能运行。 我使用的值直接与记录的示例 此处相对应。 确保将其替换为您自己的值。
var oauth_token = "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw";
var oauth_token_secret = "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA";
var oauth_consumer_key = "GDdmIQH6jhtmLUypg82g";
var oauth_consumer_secret = "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98";
我们还需要定义有关请求的一些详细信息。 这包括一个唯一的 oauth_nonce
参数,该参数必须为每个请求生成,以及一个时间戳。
var oauth_version = "1.0";
var oauth_signature_method = "HMAC-SHA1";
var oauth_nonce = Convert.ToBase64String(
new ASCIIEncoding().GetBytes(
DateTime.Now.Ticks.ToString()));
var timeSpan = DateTime.UtcNow
- new DateTime(1970, 1, 1, 0, 0, 0, 0,
DateTimeKind.Utc);
var oauth_timestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString();
var resource_url = "https://api.twitter.com/1.1/statuses/update.json";
var status = "Updating status via REST API if this works";
下一步是生成一个加密的 oAuth 签名,Twitter 将使用该签名来验证请求。 为此,所有请求数据都将按照以下特定格式连接在一起。
var baseFormat = "oauth_consumer_key={0}&oauth_nonce={1}&oauth_signature_method={2}" +
"&oauth_timestamp={3}&oauth_token={4}&oauth_version={5}&status={6}";
var baseString = string.Format(baseFormat,
oauth_consumer_key,
oauth_nonce,
oauth_signature_method,
oauth_timestamp,
oauth_token,
oauth_version,
Uri.EscapeDataString(status)
);
baseString = string.Concat("POST&", Uri.EscapeDataString(resource_url),
"&", Uri.EscapeDataString(baseString));
使用此基本字符串,然后我们使用密钥和 HMAC-SHA1 算法的组合对数据进行加密。
var compositeKey = string.Concat(Uri.EscapeDataString(oauth_consumer_secret),
"&", Uri.EscapeDataString(oauth_token_secret));
string oauth_signature;
using (HMACSHA1 hasher = new HMACSHA1(ASCIIEncoding.ASCII.GetBytes(compositeKey)))
{
oauth_signature = Convert.ToBase64String(
hasher.ComputeHash(ASCIIEncoding.ASCII.GetBytes(baseString)));
}
然后,oAuth 签名用于生成身份验证标头。 这需要将公钥和上面生成的令牌连接成以下格式。
var headerFormat = "OAuth oauth_nonce=\"{0}\", oauth_signature_method=\"{1}\", " +
"oauth_timestamp=\"{2}\", oauth_consumer_key=\"{3}\", " +
"oauth_token=\"{4}\", oauth_signature=\"{5}\", " +
"oauth_version=\"{6}\"";
var authHeader = string.Format(headerFormat,
Uri.EscapeDataString(oauth_nonce),
Uri.EscapeDataString(oauth_signature_method),
Uri.EscapeDataString(oauth_timestamp),
Uri.EscapeDataString(oauth_consumer_key),
Uri.EscapeDataString(oauth_token),
Uri.EscapeDataString(oauth_signature),
Uri.EscapeDataString(oauth_version)
);
我们现在准备好发送请求,这很容易。 请注意,我们还必须使用 ServicePointManager
禁用 Expect: 100-Continue 标头。 如果没有此代码,.NET 默认会发送该标头,而 Twitter 不支持该标头。
var postBody = "status=" + Uri.EscapeDataString(status);
ServicePointManager.Expect100Continue = false;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(resource_url);
request.Headers.Add("Authorization", authHeader);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
using (Stream stream = request.GetRequestStream())
{
byte[] content = ASCIIEncoding.ASCII.GetBytes(postBody);
stream.Write(content, 0, content.Length);
}
WebResponse response = request.GetResponse();
摘要
希望此示例展示了如何以相当小的努力来实现 OAuth。 在提供的示例中,为了清楚起见,我将所有内容都保留在了行内; 但是,在现实世界中,您显然会将代码重构为更合理的层。
通过这种方式,可以构建一些高度可测试的轻量级类,以便生成所需的消息签名、发出请求并处理响应。