2013-06-15 4 views
3

У меня есть приложение для Windows 8 и Windows Phone 8, которое служит в качестве панели инструментов для социальных сетей, и это твиты get, использующие twit search api. Первоначально это было реализовано с использованием API-интерфейса Twitter 1 и работало без аутентификации, так как ему не нужны никакие дополнительные сторонние библиотеки, которые были помещены в часть PCL решения. По той же причине я хотел, чтобы обновление с использованием 1.1 API выполнялось без каких-либо библиотек. Я нашел различные образцы онлайн в сообществе разработчиков Twitter и на codeproject и изменил их для работы с PCL.Twitter API 1.1 Поиск с C# (в PCL)

Вот часть кода, пытающегося искать твиттер:

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; } 
    } 

N.B.:The AsciiEncoding обычай реализации ASCIIEncoding, поскольку он не доступен в PCL в данный момент.

Теперь я попытался стандартную отладку и первое, что я смотрел на был инструмент Twitter OAuth и здесь приведены результаты OAuth инструментов против моего приложения

OAuth Tool Подпись базовая строка:

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 

Мое приложение Подпись базовая строка:

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 

И на первый взгляд единственным отличием является одноразовое значение, но это не должно быть проблемой Редактирование заметки: Я только что заметил, что в приведенном выше примере есть небольшая разница в том, что в OAuth Tool у меня есть% 26q% 3Dcsmcr, и мое приложение генерирует% 26q% 3D% 2540csmcr, но это просто так как я забыл включить символ в запрос в инструмент OAuth. После добавления символа строка стала одинаковой в конце.

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" 

Мое приложение Authorization заголовок:

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" 

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

Таким образом, проблема, что у меня есть то, что при выполнении функции я всегда получаю 401 Несанкционированной ошибку с ошибкой

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

.

Любые указатели будут очень признательны.

Edit: еще некоторое тестирование с этим, взял одноразовый номер и метку времени, порожденный инструментом Twitter OAuth и просто зашиты их в мое приложение, чтобы проверить, если подпись была в порядке, и оказалось, что это было так, я был получение той же самой oauth_signature, что и в инструменте OAuth. Это означало бы, что заголовок Auth также должен быть полностью прав. Поэтому я предполагаю, что проблема находится где-то в моей просьбе.

ответ

0

(Ответы OP в вопросе редактирования. Преобразование в ответ на wiki сообщества.См Question with no answers, but issue solved in the comments (or extended in chat))

ОП писал:

Проблема решена путем замены httpwebrequest реализации с httpclient. Проблема заключалась в том, что заголовок Expect:100-Continue добавлялся, и твиттер не поддерживает это. Из-за ограничений в PCL было невозможно отключить это в httpwebrequest, заменив все это на httpclie. Надеюсь, это поможет любому, кто испытывает ту же проблему.