我同意你的看法。可用于 .NET 应用程序的开源 OAuth 支持类很难理解、过于复杂(DotNetOpenAuth 公开了多少方法?)、设计不佳(查看来自 google 的 OAuthBase.cs 模块中具有 10 个字符串参数的方法)您提供的链接 - 根本没有状态管理),或者其他方面不满意。
不需要这么复杂。
我不是 OAuth 方面的专家,但我已经制作了一个 OAuth 客户端管理器类,我成功地将其与 Twitter 和 TwitPic 一起使用。使用起来相对简单。它是开源的,可在此处获取:Oauth.cs
回顾一下,在 OAuth 1.0a 中……有点有趣,有一个特殊的名称,它看起来像一个“标准”,但据我所知,实现“OAuth 1.0a”的唯一服务是 Twitter。我想这是标准的enough。好的,无论如何,在 OAuth 1.0a 中,它的工作方式对于桌面应用程序这是:
您,应用程序的开发者,注册应用程序并获得“消费者密钥”和“消费者秘密”。在 Arstechnica 上,有详细分析了为什么这个模型不是最好的,但正如他们所说,就是这样.
-
您的应用程序运行。第一次运行时,它需要让用户明确批准应用程序向 Twitter 及其姐妹服务(如 TwitPic)发出经过 oauth 身份验证的 REST 请求。为此,您必须经过批准流程,包括用户的明确批准。这种情况仅在应用程序第一次运行时发生。像这样:
- 请求“请求令牌”。又名临时令牌。
- 弹出一个网页,将该请求令牌作为查询参数传递。此网页向用户呈现 UI,询问“您想授予对此应用程序的访问权限吗?”
- 用户登录 Twitter 网页,并授予或拒绝访问权限。
- 出现响应 html 页面。如果用户已授予访问权限,则会以 48 磅字体显示 PIN
- 用户现在需要将该引脚剪切/粘贴到 Windows 表单框中,然后单击“下一步”或类似的操作。
- 然后,桌面应用程序会对“访问令牌”发出经过 oauth 身份验证的请求。另一个 REST 请求。
- 桌面应用程序接收“访问令牌”和“访问密钥”。
在批准舞蹈之后,桌面应用程序可以仅使用用户特定的“访问令牌”和“访问秘密”(以及应用程序特定的“消费者密钥”和“消费者秘密”)代表用户执行经过身份验证的请求到推特。这些不会过期,但如果用户取消对应用程序的授权,或者 Twitter 出于某种原因取消对您的应用程序的授权,或者如果您丢失了访问令牌和/或秘密,则您需要再次进行批准舞蹈。
如果您不聪明,UI 流可以在某种程度上反映多步骤 OAuth 消息流。有一个更好的办法。
使用 WebBrowser 控件,并在桌面应用程序中打开授权网页。当用户单击“允许”时,从该 WebBrowser 控件中获取响应文本,自动提取 PIN,然后获取访问令牌。您发送 5 或 6 个 HTTP 请求,但用户只需要看到一个允许/拒绝对话框。简单的。
Like this:
如果您已经对 UI 进行了排序,那么剩下的唯一挑战就是生成 oauth 签名的请求。这让很多人感到困惑,因为认证签名要求有些特殊。这就是简化的 OAuth Manager 类的作用。
请求令牌的示例代码:
var oauth = new OAuth.Manager();
// the URL to obtain a temporary "request token"
var rtUrl = "https://api.twitter.com/oauth/request_token";
oauth["consumer_key"] = MY_APP_SPECIFIC_KEY;
oauth["consumer_secret"] = MY_APP_SPECIFIC_SECRET;
oauth.AcquireRequestToken(rtUrl, "POST");
就是这样。简单的。从代码中可以看出,获取 oauth 参数的方法是通过基于字符串的索引器,类似于字典。 AcquireRequestToken 方法将 oauth 签名的请求发送到授予请求令牌(也称为临时令牌)的服务的 URL。对于 Twitter,此 URL 是“https://api.twitter.com/oauth/request_token“。oauth 规范表示,您需要以某种方式(url 编码并由&符号连接)打包 oauth 参数集(token、token_secret、nonce、timestamp、consumer_key、version 和callback),并以按字典顺序排序,在该结果上生成签名,然后将这些相同的参数与签名一起打包,以不同的方式存储在新的 oauth_signature 参数中(用逗号连接)。OAuth 管理器类会自动为您完成此操作。它生成随机数、时间戳和版本和签名自动 - 您的应用程序不需要关心或了解这些东西。只需设置 oauth 参数值并进行简单的方法调用即可。管理器类发出请求并为您解析响应。
好吧,然后呢?获得请求令牌后,您将弹出 Web 浏览器 UI,用户将在其中明确授予批准。如果你做得正确,你会在嵌入式浏览器中弹出它。对于 Twitter,其 URL 是“https://api.twitter.com/oauth/authorize?oauth_token=" 并附加了 oauth_token。在代码中执行此操作,如下所示:
var url = SERVICE_SPECIFIC_AUTHORIZE_URL_STUB + oauth["token"];
webBrowser1.Url = new Uri(url);
(如果您在外部浏览器中执行此操作,则可以使用System.Diagnostics.Process.Start(url)
.)
设置 Url 属性会使 WebBrowser 控件自动导航到该页面。
当用户单击“允许”按钮时,将加载新页面。它是一个 HTML 表单,其工作方式与在完整浏览器中相同。在代码中,为 WebBrowser 控件的 DocumentedCompleted 事件注册一个处理程序,然后在该处理程序中获取引脚:
var divMarker = "<div id=\"oauth_pin\">"; // the div for twitter's oauth pin
var index = webBrowser1.DocumentText.LastIndexOf(divMarker) + divMarker.Length;
var snip = web1.DocumentText.Substring(index);
var pin = RE.Regex.Replace(snip,"(?s)[^0-9]*([0-9]+).*", "$1").Trim();
这是一些 HTML 屏幕抓取。
获取 PIN 码后,您不再需要网络浏览器,因此:
webBrowser1.Visible = false; // all done with the web UI
...并且您可能还想对其调用 Dispose() 。
下一步是通过与该 pin 一起发送另一条 HTTP 消息来获取访问令牌。这是另一个签名的 oauth 调用,使用我上面描述的 oauth 排序和格式构建。但使用 OAuth.Manager 类这又非常简单:
oauth.AcquireAccessToken(URL_ACCESS_TOKEN,
"POST",
pin);
对于 Twitter,该 URL 是“https://api.twitter.com/oauth/access_token".
现在您拥有访问令牌,并且可以在签名的 HTTP 请求中使用它们。像这样:
var authzHeader = oauth.GenerateAuthzHeader(url, "POST");
...在哪里url
是资源端点。要更新用户的状态,它将是“http://api.twitter.com/1/statuses/update.xml?status=Hello".
然后将该字符串设置到名为的 HTTP 标头中授权.
要与第三方服务(例如 TwitPic)交互,您需要构建一个稍微不一样OAuth 标头,如下所示:
var authzHeader = oauth.GenerateCredsHeader(URL_VERIFY_CREDS,
"GET",
AUTHENTICATION_REALM);
对于 Twitter,验证信用 url 和领域的值为“https://api.twitter.com/1/account/verify_credentials.json", and "http://api.twitter.com/“ 分别。
...然后把thatHTTP 标头中的授权字符串称为X-验证-凭据-授权。然后将其与您发送的任何请求一起发送到您的服务,例如 TwitPic。
就是这样。
总而言之,更新 Twitter 状态的代码可能如下所示:
// the URL to obtain a temporary "request token"
var rtUrl = "https://api.twitter.com/oauth/request_token";
var oauth = new OAuth.Manager();
// The consumer_{key,secret} are obtained via registration
oauth["consumer_key"] = "~~~CONSUMER_KEY~~~~";
oauth["consumer_secret"] = "~~~CONSUMER_SECRET~~~";
oauth.AcquireRequestToken(rtUrl, "POST");
var authzUrl = "https://api.twitter.com/oauth/authorize?oauth_token=" + oauth["token"];
// here, should use a WebBrowser control.
System.Diagnostics.Process.Start(authzUrl); // example only!
// instruct the user to type in the PIN from that browser window
var pin = "...";
var atUrl = "https://api.twitter.com/oauth/access_token";
oauth.AcquireAccessToken(atUrl, "POST", pin);
// now, update twitter status using that access token
var appUrl = "http://api.twitter.com/1/statuses/update.xml?status=Hello";
var authzHeader = oauth.GenerateAuthzHeader(appUrl, "POST");
var request = (HttpWebRequest)WebRequest.Create(appUrl);
request.Method = "POST";
request.PreAuthenticate = true;
request.AllowWriteStreamBuffering = true;
request.Headers.Add("Authorization", authzHeader);
using (var response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode != HttpStatusCode.OK)
MessageBox.Show("There's been a problem trying to tweet:" +
Environment.NewLine +
response.StatusDescription);
}
OAuth 1.0a 在幕后有点复杂,但使用它并不需要如此。
OAuth.Manager 处理传出 oauth 请求的生成以及响应中 oauth 内容的接收和处理。当 Request_token 请求为您提供 oauth_token 时,您的应用程序不需要存储它。 Oauth.Manager 足够智能,可以自动执行此操作。同样,当 access_token 请求返回访问令牌和机密时,您不需要显式存储它们。 OAuth.Manager 为您处理该状态。
在后续运行中,当您已经拥有访问令牌和密钥时,您可以像这样实例化 OAuth.Manager:
var oauth = new OAuth.Manager();
oauth["consumer_key"] = CONSUMER_KEY;
oauth["consumer_secret"] = CONSUMER_SECRET;
oauth["token"] = your_stored_access_token;
oauth["token_secret"] = your_stored_access_secret;
...然后如上所述生成授权标头。
// now, update twitter status using that access token
var appUrl = "http://api.twitter.com/1/statuses/update.xml?status=Hello";
var authzHeader = oauth.GenerateAuthzHeader(appUrl, "POST");
var request = (HttpWebRequest)WebRequest.Create(appUrl);
request.Method = "POST";
request.PreAuthenticate = true;
request.AllowWriteStreamBuffering = true;
request.Headers.Add("Authorization", authzHeader);
using (var response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode != HttpStatusCode.OK)
MessageBox.Show("There's been a problem trying to tweet:" +
Environment.NewLine +
response.StatusDescription);
}
您可以下载此处包含 OAuth.Manager 类的 DLL。该下载中还有一个帮助文件。或者你可以在线查看帮助文件.
查看使用此管理器的 Windows 窗体示例here.
工作示例
下载工作示例使用此处描述的类和技术的命令行工具: