在.NET中使用validation的OAuth

我试图创build一个基于.NET的客户端应用程序(在WPF中 – 虽然暂时我只是做一个控制台应用程序)与OAuth启用的应用程序,特别是门德利( http:// dev .mendeley.com ),这显然使用三脚OAuth。

这是我第一次使用OAuth,我开始使用它很困难。 我发现了几个.NET OAuth库或帮助程序,但它们似乎比我想的要复杂得多。 我所要做的就是能够向Mendeley API发出REST请求并获得响应!

到目前为止,我已经尝试过:

  • DotNetOpenAuth
  • http://github.com/bittercoder/DevDefined.OAuth
  • http://oauth.googlecode.com/svn/code/csharp/

第一个(DotNetOpenAuth)似乎可以做我所需要的,如果我花了几个小时试图解决问题。 第二和第三,尽我所知,不支持门德利送回的validation码 – 虽然我可能是错误的:)

我有一个来自Mendeley的消费者密钥和秘密,通过DotNetOpenAuth,我设法使用Mendeley页面启动浏览器,为用户提供validation码,以便进入应用程序。 然而,在这一点上,我迷路了,不能解决如何明智地提供回应用程序。

我非常愿意承认,我不知道从哪里开始(虽然看起来有相当陡峭的学习曲线) – 如果任何人都可以指出我正确的方向,我会很感激!

我赞同你。 可用于.NET应用程序的开源OAuth支持类很难理解,过于复杂(DotNetOpenAuth公开了多less种方法?),devise不佳(查看来自谷歌的OAuthBase.cs模块中包含10个string参数的方法链接你提供 – 根本没有国家pipe理),否则不令人满意。

它不需要这么复杂。

我不是OAuth的专家,但是我已经开发了一个OAuth客户端pipe理器类,我成功地使用了Twitter和TwitPic。 使用起来相对简单。 这是开源的,可在这里find: Oauth.cs

审查,在OAuth 1.0A …有趣的是,有一个特殊的名称,它看起来像一个“标准”,但据我所知,实现“OAuth 1.0A”唯一的服务是Twitter。 我想这足够标准。 好吧,无论如何,在OAuth 1.0A,它的桌面应用程序的工作方式是这样的:

  1. 你,应用程序的开发者,注册应用程序,并获得“消费者密钥”和“消费者的秘密”。 在Arstechnica,有一篇关于为什么这个模型不是最好的分析的书面分析 ,但正如他们所说的那样。

  2. 你的应用程序运行 第一次运行时,需要让用户明确地批准应用程序,以便向Twitter及其姊妹服务(如TwitPic)进行oauthauthentication的REST请求。 要做到这一点,你必须经过审批过程,涉及用户的明确的批准。 这只发生在应用程序第一次运行。 喜欢这个:

    • 请求“请求令牌”。 又名临时令牌。
    • popup一个网页,将该请求令牌作为查询parameter passing。 这个网页向用户展示用户界面,询问“你想授予访问这个应用程序?”
    • 用户login到Twitter网页,并授予或拒绝访问。
    • 出现响应html页面。 如果用户已经授予访问权限,则以48磅字体显示PIN
    • 用户现在需要剪切/粘贴到Windows窗体框中,然后单击“下一步”或类似的东西。
    • 桌面应用程序然后执行oauthauthentication的“访问令牌”请求。 另一个REST请求。
    • 桌面应用程序收到“访问令牌”和“访问秘密”。

在批准舞蹈之后,桌面应用程序可以仅使用用户特定的“访问令牌”和“访问秘密”(连同应用程序特定的“消费者密钥”和“消费者机密”)来代表用户进行authentication的请求到Twitter。 这些不会过期,但如果用户取消授权应用程序,或者由于某种原因,Twitter取消了对您的应用程序的授权,或者您失去了访问令牌和/或秘密,则需要再次进行审批。


如果你不聪明,UIstream可以对多步OAuth消息stream进行镜像。 有一个更好的办法。

使用WebBrowser控件,并在桌面应用程序中打开授权网页。 当用户点击“允许”时,从WebBrowser控件获取响应文本,自动提取PIN码,然后获取访问令牌。 您发送5或6个HTTP请求,但用户只需要看到一个允许/拒绝对话框。 简单。

喜欢这个:
替代文字


如果你已经对UI进行了sorting,唯一的挑战就是产生oauth签名的请求。 这使得很多人因为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参数的方法是通过基于string的索引器,就像字典一样。 AcquireRequestToken方法将oauth签名的请求发送给授予请求令牌的服务的URL,也就是临时令牌。 对于Twitter,这个URL是“ https://api.twitter.com/oauth/request_token ”。 oauth规范说,您需要以某种方式(url编码并通过&符号连接)打包一组oauth参数(token,token_secret,nonce,timestamp,consumer_key,version和callback),并以字典的forms – 对结果生成一个签名,然后用不同的方式(用逗号连接)将这些参数与存储在新的oauth_signature参数中的签名一起打包。 OAuthpipe理员类会自动为您执行此操作。 它会自动生成随机数和时间戳,版本和签名 – 您的应用程序不需要关心或意识到这些东西。 只需设置oauth参数值并进行简单的方法调用即可。 经理类发出请求并为您parsing响应。

好的,那么是什么? 一旦获得请求令牌,就会popup用户将明确授予批准的Web浏览器UI。 如果你做对了,你会在embedded式浏览器中popup。 对于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控件自动导航到该页面。

当用户点击“允许”button时,一个新的页面将被加载。 这是一个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屏幕抓取。

抓住引脚后,不再需要networking浏览器,所以:

 webBrowser1.Visible = false; // all done with the web UI 

…你也可能想调用Dispose()。

下一步是通过发送另一个HTTP消息以及该引脚来获取访问令牌。 这是另一个签名的oauth调用,用上面描述的oauth命令和格式构build。 但是,对于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 ”。

然后将该string设置到名为Authorization的HTTP Header中。

要与TwitPic等第三方服务交互,您需要构build一个稍微不同的 OAuth标头,如下所示:

 var authzHeader = oauth.GenerateCredsHeader(URL_VERIFY_CREDS, "GET", AUTHENTICATION_REALM); 

对于Twitter,validation信用url和领域的值分别是“ https://api.twitter.com/1/account/verify_credentials.json ”和“ http://api.twitter.com/ ”。

…并将授权string放在名为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.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 。 该下载中还有一个帮助文件。 或者您可以在线查看帮助文件 。

请参阅此处使用此pipe理器的Windows窗体示例。


工作的例子

下载使用此处描述的类和技术的命令行工具的工作示例 :