Oauth、Twitter、401 未经授权

编程入门 行业动态 更新时间:2024-10-27 13:27:46
本文介绍了Oauth、Twitter、401 未经授权的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我想脱离 Twitsharp 并在 twitter 中使用用户流,为了做到这一点,我需要编写自己的 oAuth 来验证我对 API 的请求.

I want to break away from Twitsharp and utilise the User Streaming in twitter, in order to do this I need to write my own oAuth for authenticating my requests against the API.

从来没有这样做过,我真的很难实现它.我找到了一个很好的例子(garyshortblog.wordpress/2011/02/11/a-twitter-oauth-example-in-c/),我试图用它来了解如何编写我自己的.但是我什至无法让这个例子起作用.每次运行它我总是遇到 401 Unauthorized.我的令牌等很好,它们在 Twitsharp 下工作.如果我在 Twitsharp 请求和我的请求之间使用提琴手进行比较,除了 oauth_nonce 和 oauth_signature 之外,它们完全相同.

Having never had to do this I'm really struggling to implement it. I found an excellent example (garyshortblog.wordpress/2011/02/11/a-twitter-oauth-example-in-c/) which I'm attempting to use to understand how to write my own. However I can't even get the example to work. Each time run it I always encounter 401 Unauthorised. My tokens etc. are fine, they work under Twitsharp. If I make a comparison using fiddler between a Twitsharp request and mine, they are exactly the same with the exception of the oauth_nonce and oauth_signature.

这是我到目前为止所拥有的,想法很感激.

This is what I have so far, thoughts appreciated.

标题:

好 - 与 Twitsharp 合作

GOOD - Working with Twitsharp

oauth_consumer_key="xxx", oauth_nonce="eyn5x7hhj06tr8ic", oauth_signature="aZa5Fg7%2FO%2BbSlO9cYTL7OYLpkAM%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1332540179", oauth_token="xxx", oauth_version="1.0"

不好 - 我的例子

BAD - My Example

oauth_consumer_key="xxx", oauth_nonce="NjM0NjgxMzgyNDQ5MTgxMDk5", oauth_signature="bSryjrvc1t4kMaIpXCGe7uAFmUI%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1332541445", oauth_token="xxx", oauth_version="1.0"

代码:

/// <summary> /// The set of characters that are unreserved in RFC 2396 but are NOT unreserved in RFC 3986. /// </summary> private static readonly string[] UriRfc3986CharsToEscape = new[] { "!", "*", "'", "(", ")" }; /// <summary> /// Escapes a string according to the URI data string rules given in RFC 3986. /// </summary> /// <param name="value">The value to escape.</param> /// <returns>The escaped value.</returns> /// <remarks> /// The <see cref="Uri.EscapeDataString"/> method is <i>supposed</i> to take on /// RFC 3986 behavior if certain elements are present in a .config file. Even if this /// actually worked (which in my experiments it <i>doesn't</i>), we can't rely on every /// host actually having this configuration element present. /// </remarks> internal static string EscapeUriDataStringRfc3986(string value) { // Start with RFC 2396 escaping by calling the .NET method to do the work. // This MAY sometimes exhibit RFC 3986 behavior (according to the documentation). // If it does, the escaping we do that follows it will be a no-op since the // characters we search for to replace can't possibly exist in the string. StringBuilder escaped = new StringBuilder(Uri.EscapeDataString(value)); // Upgrade the escaping to RFC 3986, if necessary. for (int i = 0; i < UriRfc3986CharsToEscape.Length; i++) { escaped.Replace(UriRfc3986CharsToEscape[i], Uri.HexEscape(UriRfc3986CharsToEscape[i][0])); } // Return the fully-RFC3986-escaped string. return escaped.ToString(); } public static void UserStream() { //GS - Get the oAuth params string status = "statusUpdate112"; string postBody = "status=" + EscapeUriDataStringRfc3986(status); string oauth_consumer_key = _consumerKey; string oauth_nonce = Convert.ToBase64String( new ASCIIEncoding().GetBytes( DateTime.Now.Ticks.ToString())); string oauth_signature_method = "HMAC-SHA1"; string oauth_token = _accessToken; TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); string oauth_timestamp = Convert.ToInt64(ts.TotalSeconds).ToString(); string oauth_version = "1.0"; //GS - When building the signature string the params //must be in alphabetical order. I can't be bothered //with that, get SortedDictionary to do it's thing SortedDictionary<string, string> sd = new SortedDictionary<string, string>(); sd.Add("status", status); sd.Add("oauth_version", oauth_version); sd.Add("oauth_consumer_key", oauth_consumer_key); sd.Add("oauth_nonce", oauth_nonce); sd.Add("oauth_signature_method", oauth_signature_method); sd.Add("oauth_timestamp", oauth_timestamp); sd.Add("oauth_token", oauth_token); //GS - Build the signature string string baseString = String.Empty; baseString += "POST" + "&"; baseString += EscapeUriDataStringRfc3986( "api.twitter/1/statuses/update.json") + "&"; foreach (KeyValuePair<string, string> entry in sd) { baseString += EscapeUriDataStringRfc3986(entry.Key + "=" + entry.Value + "&"); } //GS - Remove the trailing ambersand char, remember //it's been urlEncoded so you have to remove the //last 3 chars - %26 baseString = baseString.Substring(0, baseString.Length - 3); //GS - Build the signing key string consumerSecret = _consumerSecret; string oauth_token_secret = _accessTokenSecret; string signingKey = EscapeUriDataStringRfc3986(consumerSecret) + "&" + EscapeUriDataStringRfc3986(oauth_token_secret); //GS - Sign the request HMACSHA1 hasher = new HMACSHA1( new ASCIIEncoding().GetBytes(signingKey)); string signatureString = Convert.ToBase64String( hasher.ComputeHash( new ASCIIEncoding().GetBytes(baseString))); //GS - Tell Twitter we don't do the 100 continue thing ServicePointManager.Expect100Continue = false; //GS - Instantiate a web request and populate the //authorization header HttpWebRequest hwr = (HttpWebRequest)WebRequest.Create( @"api.twitter/1/statuses/update.json"); string authorizationHeaderParams = String.Empty; authorizationHeaderParams += "OAuth "; authorizationHeaderParams += "oauth_consumer_key=" + "\"" + EscapeUriDataStringRfc3986( oauth_consumer_key) + "\","; authorizationHeaderParams += "oauth_nonce=" + "\"" + EscapeUriDataStringRfc3986(oauth_nonce) + "\","; authorizationHeaderParams += "oauth_signature=" + "\"" + EscapeUriDataStringRfc3986(signatureString) + "\","; authorizationHeaderParams += "oauth_signature_method=" + "\"" + EscapeUriDataStringRfc3986(oauth_signature_method) + "\","; authorizationHeaderParams += "oauth_timestamp=" + "\"" + EscapeUriDataStringRfc3986(oauth_timestamp) + "\","; authorizationHeaderParams += "oauth_token=" + "\"" + EscapeUriDataStringRfc3986(oauth_token) + "\","; authorizationHeaderParams += "oauth_version=" + "\"" + EscapeUriDataStringRfc3986(oauth_version) + "\""; hwr.Headers.Add( "Authorization", authorizationHeaderParams); //added user agent hwr.UserAgent = "XserT"; //GS - POST off the request hwr.Method = "POST"; hwr.ContentType = "application/x-www-form-urlencoded"; Stream stream = hwr.GetRequestStream(); byte[] bodyBytes = new ASCIIEncoding().GetBytes(postBody); stream.Write(bodyBytes, 0, bodyBytes.Length); stream.Flush(); stream.Close(); //GS - Allow us a reasonable timeout in case //Twitter's busy hwr.Timeout = 3 * 60 * 1000; try { HttpWebResponse rsp = hwr.GetResponse() as HttpWebResponse; hwr.KeepAlive = false; //GS - Do something with the return here... } catch (WebException e) { //GS - Do some clever error handling here... } }

推荐答案

Uri.EscapeDataString 没有使用正确的编码机制.

The Uri.EscapeDataString does not use correct encoding mechanism.

例如,查看有关该主题的其他帖子:

For instance, check this other post out on the subject:

如何让 Uri.EscapeDataString 符合RFC 3986

在那篇文章中,您会发现有人粘贴了正确的逃生程序.试一试!

In that post, you will find someone pasted a correct escape routine. Give it as shot!

更多推荐

Oauth、Twitter、401 未经授权

本文发布于:2023-11-09 22:39:22,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1573625.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:未经授权   Oauth   Twitter

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!