2012-03-23 19 views
0

Ich möchte von Twitsharp brechen und das User Streaming in Twitter verwenden, um dies zu tun, muss ich meine eigene oAuth für die Authentifizierung meiner Anforderungen gegen die API schreiben.Oauth, Twitter, 401 Nicht autorisiert

Da ich das nie tun musste, kämpfe ich wirklich darum, es zu implementieren. Ich fand ein hervorragendes Beispiel (http://garyshortblog.wordpress.com/2011/02/11/a-twitter-oauth-example-in-c/), das ich versuche zu verstehen, wie ich mein eigenes schreibe. Allerdings kann ich das Beispiel nicht mal zur Arbeit bringen. Jedes Mal, wenn ich es laufe, begegne ich immer 401 Unauthorized. Meine Tokens usw. sind in Ordnung, sie arbeiten unter Twitsharp. Wenn ich einen Fiddler-Vergleich zwischen einer Twitsharp-Anfrage und meiner vergleiche, sind sie genau die gleichen mit Ausnahme von oauth_nonce und oauth_signature.

Dies ist, was ich bisher, Gedanken geschätzt habe.

Headers:

GOOD - Arbeiten mit 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 Beispiel

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" 

Code:

 /// <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(
       "http://api.twitter.com/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(
       @"https://api.twitter.com/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... 
      } 



     } 
+0

Ich hoffe, Sie verwenden jetzt Ihre eigene Anwendung, nicht Twitscharps Verbraucherschlüssel? –

+0

nein? Warum sollte ich Twitsharps Verbraucherschlüssel verwenden? – Damo

Antwort

0

Ich weiß, dass dies nicht beantwortet Ihre Frage, aber wenn Sie versuchen, linqtotwitter können Sie es einfach tun.

Es gibt Beispiele, die

Ich möchte auch hinzufügen Tweetsharp wird wahrscheinlich abgeschrieben im Quellbereich arbeiten. Anfang letzten Jahres hörte er auf, daran zu arbeiten.

+0

Deshalb möchte ich das OAUTH und die API besser verstehen. Aber auf NuGet scheint es Updates von vor einem Monat zu geben .... – Damo

+0

ahh ich erinnere mich daniel crenna hörte auf, daran zu arbeiten. Er hat tweetsharp –

0

Der Uri.EscapeDataString verwendet keinen korrekten Codierungsmechanismus.

So überprüfen Sie diese andere Post aus zu dem Thema:

How to get Uri.EscapeDataString to comply with RFC 3986

In diesem Beitrag finden Sie, jemand eine richtige Flucht Routine eingefügt. Gib es als Schuss!

+0

Danke gemacht, leider hat es nicht funktioniert. Code oben aktualisiert. – Damo

Verwandte Themen