简体   繁体   English

Twitter API 1.1使用C#搜索(在PCL中)

[英]Twitter API 1.1 Search with C# (in a PCL)

I have a Windows 8 and a Windows Phone 8 app that serves as a social media dashboard and it get's tweets using the twitter search api. 我有一个Windows 8和一个Windows Phone 8应用程序作为社交媒体仪表板,它使用twitter搜索API获取推文。 This was originally implemented using the Twitter API 1 and worked with no authentication so since it didn't need any additional 3rd party libs it was placed in the PCL part of the solution. 这最初是使用Twitter API 1实现的,并且没有进行身份验证,因此它不需要任何其他第三方库,因此它被放置在解决方案的PCL部分中。 For the same reason I wanted the update to using 1.1 API to be done without any libs. 出于同样的原因,我希望更新使用1.1 API,而不需要任何库。 I have found various samples online on the Twitter dev community and on codeproject and modified them to work with the PCL. 我在Twitter开发社区和codeproject上在线发现了各种样本,并修改了它们以便与PCL一起工作。

Here is the part of the code attempting to search twitter: 以下是试图搜索twitter的代码部分:

private static async Task<string> doTheTwitterMagic(string query)
    {
        var oauth_token = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        var oauth_token_secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        var oauth_consumer_key = "XXXXXXXXXXXXXXXXX";
        var oauth_consumer_secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

        var resource_url = "https://api.twitter.com/1.1/search/tweets.json";

        // oauth implementation details
        var oauth_version = "1.0";
        var oauth_signature_method = "HMAC-SHA1";

        Encoding ascii = new AsciiEncoding();

        // unique request details
        var oauth_nonce = Convert.ToBase64String(
            ascii.GetBytes(DateTime.Now.Ticks.ToString()));
        var timeSpan = DateTime.UtcNow
            - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
        var oauth_timestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString();


        // create oauth signature
        var baseFormat = "oauth_consumer_key={0}&oauth_nonce={1}&oauth_signature_method={2}" +
                        "&oauth_timestamp={3}&oauth_token={4}&oauth_version={5}&q={6}";

        var baseString = string.Format(baseFormat,
                                    oauth_consumer_key,
                                    oauth_nonce,
                                    oauth_signature_method,
                                    oauth_timestamp,
                                    oauth_token,
                                    oauth_version,
                                    Uri.EscapeDataString(query)
                                    );

        baseString = string.Concat("GET&", Uri.EscapeDataString(resource_url), "&", Uri.EscapeDataString(baseString));

        var compositeKey = string.Concat(Uri.EscapeDataString(oauth_consumer_secret),
                                "&", Uri.EscapeDataString(oauth_token_secret));

        string oauth_signature;
        using (HMACSHA1 hasher = new HMACSHA1(ascii.GetBytes(compositeKey)))
        {
            oauth_signature = Convert.ToBase64String(
                hasher.ComputeHash(ascii.GetBytes(baseString)));
        }

        // create the request header
        var headerFormat = "OAuth oauth_nonce=\"{0}\", oauth_signature_method=\"{1}\", " +
                           "oauth_timestamp=\"{2}\", oauth_consumer_key=\"{3}\", " +
                           "oauth_token=\"{4}\", oauth_signature=\"{5}\", " +
                           "oauth_version=\"{6}\"";

        var authHeader = string.Format(headerFormat,
                                Uri.EscapeDataString(oauth_nonce),
                                Uri.EscapeDataString(oauth_signature_method),
                                Uri.EscapeDataString(oauth_timestamp),
                                Uri.EscapeDataString(oauth_consumer_key),
                                Uri.EscapeDataString(oauth_token),
                                Uri.EscapeDataString(oauth_signature),
                                Uri.EscapeDataString(oauth_version)
                        );

        return authHeader;
    }
public static async Task<List<TwitterObject>> GetTweetsFromSearchAsync(string query)
    {
        try
        {
            string authHeader = await doTheTwitterMagic(query);

            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://api.twitter.com/1.1/search/tweets.json?q="+query);
            webRequest.Headers[HttpRequestHeader.Authorization] = authHeader;
            webRequest.ContentType = "application/x-www-form-urlencoded";
            webRequest.Method = "GET";

            var webResponse = await webRequest.GetResponseAsync();
            var json = string.Empty;
            using (var reader = new StreamReader(webResponse.GetResponseStream()))
                json = await reader.ReadToEndAsync();

            var jsonObject = JObject.Parse(json);
            var results = new List<TwitterObject>();
            foreach (JToken token in jsonObject["results"])
                results.Add(token.ToObject<TwitterObject>());
            return results;
        }
        catch (Exception e) { throw e; }
    }

NB:The AsciiEncoding is a custom implementation of ASCIIEncoding since it's not available in the PCL at the moment. 注意:AsciiEncoding是ASCIIEncoding的自定义实现,因为它目前在PCL中不可用。

Now I attempted the standard debugging and the first thing I looked at was the Twitter OAuth tool and here are the results of OAuth tools vs my app 现在我尝试了标准调试,我看到的第一件事是Twitter OAuth工具,以下是OAuth工具与我的应用程序的结果

OAuth Tool Signature base string: OAuth工具签名基本字符串:

GET&https%3A%2F%2Fapi.twitter.com%2F1.1%2Fsearch%2Ftweets.json&oauth_consumer_key
%3DywWuYGASkHMsHsC22Vpw%26oauth_nonce%3D3c30afb0c2a391d3b4e4ba3da057c2ca%26oauth_
signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1371309728%26oauth_token%3D16702
294-3WNjfZ9p0QWhEDPL1jR14s5safYhiruowHa3cXWbM%26oauth_version%3D1.0%26q%3Dcsmcr

My app Signature base string: 我的应用程序签名基本字符串:

GET&https%3A%2F%2Fapi.twitter.com%2F1.1%2Fsearch%2Ftweets.json&oauth_consumer_key
%3DywWuYGASkHMsHsC22Vpw%26oauth_nonce%3DNjM1MDY5MTA1MzA2MTU1NTgz%26oauth_signatur
e_method%3DHMAC-SHA1%26oauth_timestamp%3D1371310131%26oauth_token%3D16702294-3WNj
fZ9p0QWhEDPL1jR14s5safYhiruowHa3cXWbM%26oauth_version%3D1.0%26q%3D%2540csmcr

And at the first look the only difference being the nonce but that shouldn't be an issue Edit note: I have just noticed that there is a small difference in the above at the end of the both where in the OAuth Tool one I have %26q%3Dcsmcr and my app generates %26q%3D%2540csmcr but that's just since I forgot to include a character in the query in the OAuth tool. 首先看看唯一的区别是nonce但不应该是一个问题编辑说明:我刚刚注意到,在OAuth工具的两个末尾的上面有一个小的差别我有% 26q%3Dcsmcr和我的应用程序生成%26q%3D%2540csmcr但这只是因为我忘了在OAuth工具中的查询中包含一个字符。 After adding the character the string became the same at the end. 添加字符后,字符串在结尾处变得相同。

OAuth Tool Authorization header: OAuth工具授权标题:

Authorization: OAuth oauth_consumer_key="ywWuYGASkHMsHsC22Vpw",    
oauth_nonce="3c30afb0c2a391d3b4e4ba3da057c2ca", 
oauth_signature="tofmGp6qaAUAPZnQHhQlVFWN40M%3D", 
oauth_signature_method="HMAC-SHA1", oauth_timestamp="1371309728", 
oauth_token="16702294-3WNjfZ9p0QWhEDPL1jR14s5safYhiruowHa3cXWbM", 
oauth_version="1.0"

My app Authorization header: 我的应用授权标题:

Authorization: OAuth oauth_nonce="NjM1MDY5MDk5NTY5Nzc1MTc5", 
oauth_signature_method="HMAC-SHA1", oauth_timestamp="1371309557", 
oauth_consumer_key="ywWuYGASkHMsHsC22Vpw", 
oauth_token="16702294-3WNjfZ9p0QWhEDPL1jR14s5safYhiruowHa3cXWbM", 
oauth_signature="q1544JDPUXdUwY3fmEk3mtGGEwk%3D", oauth_version="1.0"

Again not much difference other than the nonce and the signature. 除了nonce和签名之外,没有太大区别。 The order of the key-value pairs seems to make no difference as I tested with rearranging them and still had the same problem. 键值对的顺序似乎没有区别,因为我测试重新排列它们仍然有相同的问题。

So the problem that I have is that when the function runs I always get the 401 Unauthorized error with the 所以我遇到的问题是,当函数运行时,我总是得到401 Unauthorized错误

{"errors":[{"message":"Could not authenticate you","code":32}]}

error. 错误。

Any pointers would be very much appreciated. 任何指针都将非常感激。

Edit: Did some more testing with this, took the nonce and the timestamp generated by the Twitter OAuth tool and just hardcoded them in my app to check if the signature was fine and it turned out it was, I was getting the same oauth_signature as the one in the OAuth tool. 编辑:用这个进行了一些测试,接受了Twitter OAuth工具生成的随机数和时间戳,并在我的应用程序中硬编码它们以检查签名是否正常,结果是,我得到了相同的oauth_signature作为一个在OAuth工具中。 That would mean that the Auth header should also be totally fine. 这意味着Auth标头也应该完全没问题。 So I guess the problem is somewhere in my request. 所以我猜问题就在我的请求中。

(Answered by the OP in a question edit. Converted to a community wiki answer. See Question with no answers, but issue solved in the comments (or extended in chat) ) (在问题编辑中由OP回答。转换为社区维基答案。请参阅问题但没有答案,但问题已在评论中解决(或在聊天中扩展)

The OP wrote: OP写道:

Problem solved by replacing the httpwebrequest implementation with the httpclient . 通过用httpclient替换httpwebrequest实现解决了问题。 The issue was that the Expect:100-Continue header was being added, and twitter doesn't support this. 问题是正在添加Expect:100-Continue标头,而twitter不支持此功能。 Due to limitations in PCL it wasn't possible to disable this in httpwebrequest replacing it all with a httpclie nt was a way to go. 由于PCL的限制,无法在httpwebrequest禁用它,用httpclie替换它只是一种方法。 Hope this helps anyone who experiences the same issue. 希望这有助于任何遇到同样问题的人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM