我同意你的看法.开放源码的OAuth支持类可用于.NET应用程序很难理解,过于复杂(DotNetOpenAuth公开了多少方法?),设计拙劣(看看你提供的谷歌链接中OAuthBase.cs模块中有10个字符串参数的方法——根本没有状态管理),或者其他不令人满意的方法.
没必要这么复杂.
我不是OAuth方面的专家,但我已经开发了一个OAuth客户端管理器类,我成功地将其用于Twitter和TwitPic.它的使用相对简单.它是开源的,可在这里获得:Oauth.cs
回顾一下,在OAuth1.0a中……有点好笑,它有一个特殊的名字,看起来像一个"标准",但据我所知,唯一实现"OAuth1.0a"的服务是Twitter.我想那是标准的enough.好的,不管怎样,在OAuth 1.0a中,它for desktop apps的工作方式是这样的:
你,应用程序的开发者,注册应用程序,并获得一个"消费者密钥"和"消费者秘密".在Arstechnica,有a well written analysis of why this model isn't the best个,但就像他们说的,it is what it is个.
您的应用程序正在运行.在第一次运行时,它需要用户明确批准该应用程序向twitter及其姊妹服务(如twitPic)发出oauth认证的睡觉请求.要做到这一点,您必须通过一个审批流程,该流程涉及用户的显式审批.这只会在应用程序第一次运行时发生.如下所示:
- 请求"请求令牌".又名临时 token .
- 弹出一个网页,将该请求令牌作为查询参数传递.此网页向用户显示UI,询问"是否要授予此应用的访问权限?"
- 用户登录twitter网页,并授予或拒绝访问权限.
- 此时会出现响应html页面.如果用户已授予访问权限,则会以48磅字体显示PIN
- 用户现在需要将该pin剪切/粘贴到windows窗体框中,然后单击"下一步"或类似操作.
- 然后,桌面应用程序对"访问令牌"执行oauth身份验证请求.另一个休息请求.
- 桌面应用程序接收"访问令牌"和"访问密钥".
在批准舞蹈之后,桌面应用程序只需使用特定于用户的"访问令牌"和"访问密钥"(以及特定于应用程序的"消费者密钥"和"消费者密钥")就可以代表用户向Twitter发出经过身份验证的请求.这些不会过期,尽管如果用户取消了应用程序的授权,或者如果Twitter出于某种原因取消了你的应用程序的授权,或者如果你丢失了访问令牌和/或密码,你需要再次进行审批.
如果您不聪明,UI流可以在某种程度上反映多步骤OAuth消息流.还有更好的办法.
使用WebBrowser控件,并在桌面应用程序中打开授权网页.当用户单击"允许"时,从WebBrowser控件获取响应文本,自动提取PIN,然后获取访问令牌.您发送5或6个HTTP请求,但用户只需要看到一个允许/拒绝对话框.易于理解的
Like this:
如果已经对UI进行了排序,那么剩下的唯一挑战就是生成oauth签名的请求.这让很多人感到困惑,因为oauth的签名要求有点特殊.这就是简化的OAuth管理器类所做的.
请求令牌的示例代码:
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");
THAT'S IT.简单.从代码中可以看到,获取oauth参数的方法是通过基于字符串的索引器,类似于字典.AcquisiteRequestToken方法将oauth签名的请求发送到授予请求令牌(也称为临时令牌)的服务的URL.对于Twitter,这个URL是"https://api.twitter.com/oauth/request_token".oauth规范说,您需要以某种方式(url编码并由符号连接)打包oauth参数集(令牌、令牌\u secret、nonce、时间戳、使用者\u密钥、版本和回调),并按照字典排序的顺序,对该结果生成签名,然后将这些相同的参数与签名一起打包,以不同的方式存储在新的oauth_签名参数中(用逗号连接).The OAuth manager class does this for you automatically.它会自动生成nonce、时间戳和版本and signatures——你的应用不需要关心或意识到这些东西.只需设置oauth参数值并进行简单的方法调用.manager类发出请求并为您解析响应.
好吧,然后呢?获得请求令牌后,您将弹出web浏览器UI,用户将在其中明确授予批准.如果你做得对,你会在嵌入式浏览器中弹出它.对于Twitter,其URL为"https://api.twitter.com/oauth/authorize?oauth_token=",并附加了oauth_标记.在这样的代码中执行此操作:
var url = SERVICE_SPECIFIC_AUTHORIZE_URL_STUB + oauth["token"];
webBrowser1.Url = new Uri(url);
(如果在外部浏览器中执行此操作,则会使用System.Diagnostics.Process.Start(url)
.)
设置Url属性会使WebBrowser控件自动导航到该页面.
当用户单击"允许"按钮时,将加载一个新页面.这是一个HTML表单,其工作原理与在完整浏览器中相同.在代码中,为WebBrowser控件的DocumentedCompleted事件注册一个处理程序,并在该处理程序中获取pin:
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屏幕抓取.
拿到插针后,不再需要网页浏览器,所以:
webBrowser1.Visible = false; // all done with the web UI
...您可能还需要对其调用Dispose().
下一步是获取访问令牌,方法是随pin一起发送另一条HTTP消息.这是另一个有符号的oauth调用,使用我上面描述的oauth排序和格式构造.但再一次,这对于OAuth来说非常简单.经理级:
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".
然后将该字符串设置到名为Authorization的HTTP头中.
要与第三方服务(如TwitPic)交互,需要构造一个slightly different OAuth头,如下所示:
var authzHeader = oauth.GenerateCredsHeader(URL_VERIFY_CREDS,
"GET",
AUTHENTICATION_REALM);
对于Twitter,verify creds url和realm的值分别为"https://api.twitter.com/1/account/verify_credentials.json"和"http://api.twitter.com/".
.并将that个授权字符串放入名为X-Verify-Credentials-Authorization的HTTP头中.然后将其与您发送的任何请求一起发送到您的服务,如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.像这样的经理:
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);
}
你可以下载a DLL containing the OAuth.Manager class here.下载文件中还有一个帮助文件.或者你可以view the helpfile online.
请参阅使用此管理器here的Windows窗体示例.
工作示例
使用下面描述的类和技术的命令行工具的Download a working example: