如何使用 C# 进行 OAuth 1 Twitter API 调用 (dotnet core 3.1)

Pau*_*yer 2 c# twitter oauth twitter-oauth .net-core

我希望能够从 dotnet core API 服务搜索 twitter 句柄。我查看了users/search.json的 twitter 文档,并请求、借用和窃取了我可以从 stackoverflow 等获取的代码示例(见下文),但我得到的只是:

\n\n

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

\n\n

当我执行生成的curl命令时。

\n\n

抱歉,代码有点混乱,但是有人能看出我做错了什么吗?或者更好的是,如果有一个图书馆可以为我做这件事,我一直找不到一个,那就更好了。

\n\n
using Xunit;\nusing System;\nusing System.Linq;\nusing System.Collections.Generic;\nusing OAuth; // OAuth.DotNetCore, 3.0.1\nusing System.IO;\nusing System.Net;\n\nnamespace TwitterLibTest\n{\n    public class BuildHeaderTest\n    {  \n        private static readonly string consumerKey = "...";\n\n        private static readonly string consumerSecret = "...";\n\n        private static readonly string method = "GET";\n\n        private static readonly OAuthSignatureMethod oauthSignatureMethod = OAuthSignatureMethod.HmacSha1;\n\n        private static readonly string oauthVersion = "1.0a";\n\n        [Fact]\n        public void Header()\n        {\n            var url = "https://api.twitter.com/1.1/users/search.json";\n\n            var generatedNonce = RandomString(32);                        \n\n            var generatedTimestamp = DateTimeOffset.Now.ToUnixTimeSeconds().ToString();\n\n            var oauthToken = BuildAuthToken(consumerKey, consumerSecret);\n\n            var generatedSignature = GetSignatureBaseString(method, url, generatedTimestamp, generatedNonce, consumerKey, oauthToken, oauthSignatureMethod.ToString(), oauthVersion, new SortedDictionary<string, string>());\n\n            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}\\"\'");\n        }\n\n        private static Random random = new Random();\n\n        private static string RandomString(int length)\n        {\n            const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";\n            return new string(Enumerable.Repeat(chars, length)\n            .Select(s => s[random.Next(s.Length)]).ToArray());\n        }\n\n        // /sf/ask/2497439801/\n        private static string GetSignatureBaseString(string method, string strUrl, string timeStamp,\n            string nonce, string strConsumer, string strOauthToken, string oauthSignatureMethod,\n            string oauthVersion, SortedDictionary<string, string> data)\n        {\n            //1.Convert the HTTP Method to uppercase and set the output string equal to this value.\n            string Signature_Base_String = method.ToUpper();\n            Signature_Base_String = Signature_Base_String.ToUpper();\n\n            //2.Append the \xe2\x80\x98&\xe2\x80\x99 character to the output string.\n            Signature_Base_String = Signature_Base_String + "&";\n\n            //3.Percent encode the URL and append it to the output string.\n            string PercentEncodedURL = Uri.EscapeDataString(strUrl);\n            Signature_Base_String = Signature_Base_String + PercentEncodedURL;\n\n            //4.Append the \xe2\x80\x98&\xe2\x80\x99 character to the output string.\n            Signature_Base_String = Signature_Base_String + "&";\n\n            //5.append OAuth parameter string to the output string.\n            var parameters = new SortedDictionary<string, string>\n            {\n                {"oauth_consumer_key", strConsumer},\n                {"oauth_token", strOauthToken },\n                {"oauth_signature_method", oauthSignatureMethod},\n                {"oauth_timestamp", timeStamp},\n                {"oauth_nonce", nonce},\n                {"oauth_version", oauthVersion}\n            };            \n\n            //6.append parameter string to the output string.\n            foreach (KeyValuePair<string, string> elt in data)\n            {\n                parameters.Add(elt.Key, elt.Value);\n            }\n\n            bool first = true;\n            foreach (KeyValuePair<string, string> elt in parameters)\n            {\n                if (first)\n                {\n                    Signature_Base_String = Signature_Base_String + Uri.EscapeDataString(elt.Key + "=" + elt.Value);\n                    first = false;\n                }\n                else\n                {\n                    Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("&" + elt.Key + "=" + elt.Value);\n                }\n            }\n\n            return Signature_Base_String;\n        }\n\n        private string BuildAuthToken(string consumerKey, string consumerSecret)\n        {\n            var client = Client(consumerKey, consumerSecret);\n            var response = Get(client);\n            var tokenMap = Parse(response);\n\n            return tokenMap["oauth_token"];\n        }\n\n        private static OAuthRequest Client(string consumerKey, string consumerSecret)\n        {\n            return new OAuthRequest\n            {\n                Method = method,\n                Type = OAuthRequestType.RequestToken,\n                SignatureMethod = OAuthSignatureMethod.HmacSha1,\n                ConsumerKey = consumerKey,\n                ConsumerSecret = consumerSecret,\n                RequestUrl = "https://api.twitter.com/oauth/request_token",\n                Version = oauthVersion,\n            };\n        }\n\n        private static HttpWebResponse Get(OAuthRequest client)\n        {\n            string auth = client.GetAuthorizationHeader();\n            var request = (HttpWebRequest) WebRequest.Create(client.RequestUrl);           \n\n            request.Headers.Add("Authorization", auth);\n            return (HttpWebResponse) request.GetResponse();\n        }\n\n        private static Dictionary<string, string> Parse(HttpWebResponse response)\n        {\n            using var stream = response.GetResponseStream() ;\n            using var reader = new StreamReader( stream );\n            var responseAsText = reader.ReadToEnd();\n\n            var map = new Dictionary<string, string>();\n\n            foreach( var token in responseAsText.Split("&"))\n            {\n                var tokens = token.Split("=");\n                map.Add(tokens[0], tokens[1]);\n            }\n\n            return map;\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

And*_*per 6

我认为您不需要像这样单独完成所有签名和签名工作 - 这是一个也使用 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)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)