Как сделать вызов API OAuth 1 Twitter с помощью C# (do tnet core 3.1) - PullRequest
1 голос
/ 16 апреля 2020

Я хочу иметь возможность поиска хэндлов в твиттере из базовой службы API do tnet. Я посмотрел на твиттерскую документацию для users / search. json и попросил, позаимствовал и украл, какие примеры кода я могу найти в stackoverflow и т. Д. c. (см. ниже), но все, что я получаю, это:

{"errors":[{"code":215,"message":"Bad Authentication data."}]}

, когда я выполняю полученную команду curl.

Извините, код немного беспорядок, но кто-нибудь может увидеть, что я делаю неправильно? Или, что еще лучше, если есть библиотека, которая сделает это для меня, я не смог ее найти, это было бы еще лучше.

using Xunit;
using System;
using System.Linq;
using System.Collections.Generic;
using OAuth; // OAuth.DotNetCore, 3.0.1
using System.IO;
using System.Net;

namespace TwitterLibTest
{
    public class BuildHeaderTest
    {  
        private static readonly string consumerKey = "...";

        private static readonly string consumerSecret = "...";

        private static readonly string method = "GET";

        private static readonly OAuthSignatureMethod oauthSignatureMethod = OAuthSignatureMethod.HmacSha1;

        private static readonly string oauthVersion = "1.0a";

        [Fact]
        public void Header()
        {
            var url = "https://api.twitter.com/1.1/users/search.json";

            var generatedNonce = RandomString(32);                        

            var generatedTimestamp = DateTimeOffset.Now.ToUnixTimeSeconds().ToString();

            var oauthToken = BuildAuthToken(consumerKey, consumerSecret);

            var generatedSignature = GetSignatureBaseString(method, url, generatedTimestamp, generatedNonce, consumerKey, oauthToken, oauthSignatureMethod.ToString(), oauthVersion, new SortedDictionary<string, string>());

            Console.WriteLine($"curl --request GET --url '{url}?q=soccer' --header 'authorization: OAuth oauth_consumer_key=\"{consumerKey}\", oauth_nonce=\"{generatedNonce}\", oauth_signature=\"{generatedSignature}\", oauth_signature_method=\"{oauthSignatureMethod.ToString()}\", oauth_timestamp=\"{generatedTimestamp}\", oauth_token=\"{oauthToken}\", oauth_version=\"{oauthVersion}\"'");
        }

        private static Random random = new Random();

        private static string RandomString(int length)
        {
            const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            return new string(Enumerable.Repeat(chars, length)
            .Select(s => s[random.Next(s.Length)]).ToArray());
        }

        // https://stackoverflow.com/questions/35677711/generate-oauth1-signature-in-c-sharp
        private static string GetSignatureBaseString(string method, string strUrl, string timeStamp,
            string nonce, string strConsumer, string strOauthToken, string oauthSignatureMethod,
            string oauthVersion, SortedDictionary<string, string> data)
        {
            //1.Convert the HTTP Method to uppercase and set the output string equal to this value.
            string Signature_Base_String = method.ToUpper();
            Signature_Base_String = Signature_Base_String.ToUpper();

            //2.Append the ‘&’ character to the output string.
            Signature_Base_String = Signature_Base_String + "&";

            //3.Percent encode the URL and append it to the output string.
            string PercentEncodedURL = Uri.EscapeDataString(strUrl);
            Signature_Base_String = Signature_Base_String + PercentEncodedURL;

            //4.Append the ‘&’ character to the output string.
            Signature_Base_String = Signature_Base_String + "&";

            //5.append OAuth parameter string to the output string.
            var parameters = new SortedDictionary<string, string>
            {
                {"oauth_consumer_key", strConsumer},
                {"oauth_token", strOauthToken },
                {"oauth_signature_method", oauthSignatureMethod},
                {"oauth_timestamp", timeStamp},
                {"oauth_nonce", nonce},
                {"oauth_version", oauthVersion}
            };            

            //6.append parameter string to the output string.
            foreach (KeyValuePair<string, string> elt in data)
            {
                parameters.Add(elt.Key, elt.Value);
            }

            bool first = true;
            foreach (KeyValuePair<string, string> elt in parameters)
            {
                if (first)
                {
                    Signature_Base_String = Signature_Base_String + Uri.EscapeDataString(elt.Key + "=" + elt.Value);
                    first = false;
                }
                else
                {
                    Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("&" + elt.Key + "=" + elt.Value);
                }
            }

            return Signature_Base_String;
        }

        private string BuildAuthToken(string consumerKey, string consumerSecret)
        {
            var client = Client(consumerKey, consumerSecret);
            var response = Get(client);
            var tokenMap = Parse(response);

            return tokenMap["oauth_token"];
        }

        private static OAuthRequest Client(string consumerKey, string consumerSecret)
        {
            return new OAuthRequest
            {
                Method = method,
                Type = OAuthRequestType.RequestToken,
                SignatureMethod = OAuthSignatureMethod.HmacSha1,
                ConsumerKey = consumerKey,
                ConsumerSecret = consumerSecret,
                RequestUrl = "https://api.twitter.com/oauth/request_token",
                Version = oauthVersion,
            };
        }

        private static HttpWebResponse Get(OAuthRequest client)
        {
            string auth = client.GetAuthorizationHeader();
            var request = (HttpWebRequest) WebRequest.Create(client.RequestUrl);           

            request.Headers.Add("Authorization", auth);
            return (HttpWebResponse) request.GetResponse();
        }

        private static Dictionary<string, string> Parse(HttpWebResponse response)
        {
            using var stream = response.GetResponseStream() ;
            using var reader = new StreamReader( stream );
            var responseAsText = reader.ReadToEnd();

            var map = new Dictionary<string, string>();

            foreach( var token in responseAsText.Split("&"))
            {
                var tokens = token.Split("=");
                map.Add(tokens[0], tokens[1]);
            }

            return map;
        }
    }
}

Ответы [ 2 ]

2 голосов
/ 16 апреля 2020

Я не думаю, что вам нужно делать все вещи для подписи и подписи отдельно - вот пример проекта , который также использует OAuth.DotNetCore, который делает" это для вас". В этом случае я использовал HttpWebRequest напрямую, вместо того, чтобы использовать команду curl.

using System;
using OAuth;
using System.Net;
using System.IO;

namespace TwitterDotNetCore
{

  class Program
  {
    static void Main(string[] args)
    {
      // convenient to load keys and tokens from a config file for testing
      // edit .env to add your keys and tokens (no quotation marks)
      DotNetEnv.Env.Load();

      string CONSUMER_KEY = System.Environment.GetEnvironmentVariable("CONSUMER_KEY");
      string CONSUMER_TOKEN = System.Environment.GetEnvironmentVariable("CONSUMER_TOKEN");
      string ACCESS_TOKEN = System.Environment.GetEnvironmentVariable("ACCESS_TOKEN");
      string ACCESS_TOKEN_SECRET = System.Environment.GetEnvironmentVariable("ACCESS_TOKEN_SECRET");

      // this is the endpoint we will be calling
      string REQUEST_URL = "https://api.twitter.com/1.1/users/search.json?q=soccer";

      // Create a new connection to the OAuth server, with a helper method
      OAuthRequest client = OAuthRequest.ForProtectedResource("GET", CONSUMER_KEY, CONSUMER_TOKEN, ACCESS_TOKEN, ACCESS_TOKEN_SECRET);
      client.RequestUrl = REQUEST_URL;

      // add HTTP header authorization
      string auth = client.GetAuthorizationHeader();
      HttpWebRequest request = (HttpWebRequest)WebRequest.Create(client.RequestUrl);
      request.Headers.Add("Authorization", auth);

      Console.WriteLine("Calling " + REQUEST_URL);

      // make the call and print the string value of the response JSON
      HttpWebResponse response = (HttpWebResponse)request.GetResponse();
      Stream dataStream = response.GetResponseStream();
      StreamReader reader = new StreamReader(dataStream);
      string strResponse = reader.ReadToEnd();

      Console.WriteLine(strResponse); // we have a string (JSON)
    }
  }
}
1 голос
/ 19 апреля 2020

Оказывается, все, что мне нужно было https://github.com/linvi/tweetinvi и:

Auth.SetUserCredentials(APIkey, APISecretKey, AccessToken, AccessTokenSecret);
Search.SearchUsers("...").Select(u => ...);
...