2017-02-25 9 views
0

트위터에 싱글 사용자 OAuth를 사용하여 트위터 API에 대한 검색을 시도하고 있습니다. (여기에 원래 작업을 기반으로 : https://blog.dantup.com/2016/07/simplest-csharp-code-to-post-a-tweet-using-oauth) https://gist.github.com/EelcoKoster/326aa7d1b1338806b058ddcc404622b6트위터 요청이 콜론 문자가있는 경우 단일 사용자 OAuth가 실패 함

:

그러나, 나는이 라이브러리에 쿼리를 전송하고 일반 텍스트 검색에 대한 결과를 얻을 수 있지만, 그것은 초크 나는 나를 이렇게하자이 도움이 라이브러리를 발견 geocode : 26.201461, -98.237987,0.25mi

몇 가지 테스트를 마친 후 문제가되는 콜론 : 문자가 표시됩니다. 쿼리에서 제거하면 트위터에 문자열이 없기 때문에 결과가 비어 있지만 성공합니다. 다시 추가하면 오류가 발생합니다. 인증 할 수 없습니다.

매개 변수의 인코딩을 시도했지만 어디에도 없습니다.

는 내가 API 콘솔이 같은 권한 사용하고있는 것으로 나타나는이, 수행 할 수 있습니다 확신 : https://dev.twitter.com/rest/tools/console

을하고 나는 그런 검색을 할 수있는, 그래서 내 서명에 문제가되어야합니다. 내가 잘못 여기서 뭘하는지

public Task<string> Search(string search) 
    { 
     // search = Uri.EscapeDataString(search); 
     return SendRequest("search/tweets.json?q=geocode:26.201461,-98.237987,0.25mi", HttpMethod.GET, new Dictionary<string, string>()); 
    } 

    Task<string> SendRequest(string url, HttpMethod httpMethod, Dictionary<string, string> data) 
    { 
     var fullUrl = TwitterApiBaseUrl + url; 
     Random rand = new Random(); 

     // Timestamps are in seconds since 1/1/1970. 
     var timestamp = (int) ((DateTime.UtcNow - epochUtc).TotalSeconds); 

     // Add all the OAuth headers and querystring parameters, we'll need to use when constructing the hash. 
     var query = url.Split('?'); 
     if (query.Count() > 1) 
     { 
      if (data == null) data = new Dictionary<string, string>(); 
      var pairs = query[1].Split('&'); 
      foreach (var pair in pairs) 
      { 
       var keyvalue = pair.Split('='); 
       data.Add(keyvalue[0], keyvalue[1]); 
      } 
     } 
     data.Add("oauth_consumer_key", consumerKey); 
     data.Add("oauth_signature_method", "HMAC-SHA1"); 
     data.Add("oauth_timestamp", timestamp.ToString()); 
     data.Add("oauth_nonce", rand.Next(10000000, 999999999).ToString()); 
     data.Add("oauth_token", accessToken); 
     data.Add("oauth_version", "1.0"); 

     // Generate the OAuth signature and add it to our payload. 
     data.Add("oauth_signature", GenerateSignature(fullUrl, data, httpMethod)); 

     // Build the OAuth HTTP Header from the data. 
     string oAuthHeader = GenerateOAuthHeader(data); 

     switch (httpMethod) 
     { 
      case HttpMethod.GET: 
       return SendRequest(fullUrl, oAuthHeader, null, httpMethod); 
      case HttpMethod.POST: 
       var formData = new FormUrlEncodedContent(data.Where(kvp => !kvp.Key.StartsWith("oauth_"))); 
       return SendRequest(fullUrl, oAuthHeader, formData, httpMethod); 
      default: return null; 
     } 
    } 

    /// <summary> 
    /// Generate an OAuth signature from OAuth header values. 
    /// </summary> 
    string GenerateSignature(string url, Dictionary<string, string> data, HttpMethod httpMethod) 
    { 
     var sigString = string.Join(
      "&", 
      data 
       .Union(data) 
       .Select(kvp => string.Format("{0}={1}", WebUtility.UrlEncode(kvp.Key), WebUtility.UrlEncode(kvp.Value))) 
       .OrderBy(s => s) 
     ); 

     string urlWithoutParameters = url.Split('?')[0]; 

     var fullSigData = string.Format(
      "{0}&{1}&{2}", 
      httpMethod.ToString(), 
      Uri.EscapeDataString(urlWithoutParameters), 
      Uri.EscapeDataString(sigString.ToString()) 
     ); 

     return Convert.ToBase64String(sigHasher.ComputeHash(new ASCIIEncoding().GetBytes(fullSigData.ToString()))); 
    } 

    /// <summary> 
    /// Generate the raw OAuth HTML header from the values (including signature). 
    /// </summary> 
    string GenerateOAuthHeader(Dictionary<string, string> data) 
    { 
     return "OAuth " + string.Join(
      ",", 
      data 
       .Where(kvp => kvp.Key.StartsWith("oauth_")) 
       .Select(kvp => string.Format("{0}=\"{1}\"", Uri.EscapeDataString(kvp.Key), Uri.EscapeDataString(kvp.Value))) 
       .OrderBy(s => s) 
     ); 
    } 

사람이 볼 수

이 관련 코드 (내가 열심히 테스트를 위해 내 쿼리를 코딩 한)입니까?

답변

0

아하는 게시 직후에 해결책을 발견했습니다. 제 경우의 문제는 쿼리 문자열이 인코딩되는 것입니다.하지만 분명히 요청을하는 URL과 정확하게 일치해야합니다. 일치하는 URL을 인코딩하지 않으므로 오류가 발생합니다.

원본 URL의 쿼리 문자열 값을 UrlEncode로 수정하여 서명에 제출 된 내용과 일치하도록 코드를 수정해야합니다. 이것은 다른 사람에게 도움이된다

Task<string> SendRequest(string url, HttpMethod httpMethod, Dictionary<string, string> data) 
    { 
     var fullUrl = TwitterApiBaseUrl; 

     // ... 

     var query = url.Split('?'); 
     if (query.Count() > 1) 
     { 
      fullUrl += query[0] + "?"; 
      if (data == null) data = new Dictionary<string, string>(); 
      var pairs = query[1].Split('&'); 
      foreach (var pair in pairs) 
      { 
       var keyvalue = pair.Split('='); 
       data.Add(keyvalue[0], keyvalue[1]); 
       fullUrl += keyvalue[0] + "=" + WebUtility.UrlEncode(keyvalue[1]) + "&"; 
      } 

      fullUrl = fullUrl.TrimEnd('&'); 
     } 
     else 
     { 
      fullUrl += url; 
     } 

     // ... 
    } 

희망 :

날 여기 계속 할 수 신속하고 더러운 솔루션입니다!