2012-02-17 17 views
5

Tôi đang cố xác thực API Flickr cho một ứng dụng demo mà tôi muốn tạo cho chính mình. Sau đó, tôi sẽ mở rộng ứng dụng này với các tính năng mới mà tôi sẽ tìm hiểu về API của Flick.Chữ ký không hợp lệ để ký yêu cầu vào API Flickr (mô phỏng trong bảng điều khiển)

Vì vậy, đây chỉ là thứ tôi muốn chơi cùng. Nhưng bây giờ tôi gặp một số rắc rối khi nhận mã thông báo yêu cầu.

Tôi đang theo tài liệu Flickr xác thực ở đây: Flickr Authentication
Và tôi cũng thấy điều này Mathlabscript: Flickr API with OAuth-based user authentication

Vì vậy, dựa trên những nguồn tôi có bây giờ là ứng dụng giao diện điều khiển sau:

class Program 
{ 
    private static string Secret = "2b2b2b2b2b2b2b2b2b"; 
    private static string ConsumerKey = "1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a"; 

    static void Main(string[] args) 
    { 
     Random rand = new Random(); 

     string nonce = rand.Next(9999999).ToString(); 
     string timestamp = ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString(); 

     Console.WriteLine("Nonce: " + nonce); 
     Console.WriteLine("TimeStamp: " + timestamp); 

     Console.WriteLine("ConsumerKey: " + ConsumerKey); 
     Console.WriteLine("AppSecret: " + Secret); 

     //request url 
     StringBuilder b = new StringBuilder(); 
     b.Append("http://www.flickr.com/services/oauth/request_token"); 
     b.Append("?"); 
     b.Append("oauth_nonce="); 
     b.Append(nonce); 
     b.Append("&oauth_timestamp="); 
     b.Append(timestamp); 
     b.Append("&oauth_consumer_key="); 
     b.Append(ConsumerKey); 
     b.Append("&oauth_callback=oob"); 
     b.Append("&oauth_signature_method=HMAC-SHA1"); 

     string requesturl = b.ToString(); 
     Console.WriteLine("RequestUrl: " + requesturl); 

     //base url 
     string basestring; 
     StringBuilder bs = new StringBuilder(); 

     bs.Append("GET&"); 
     bs.Append(UrlHelper.Encode("http://www.flickr.com/services/oauth/request_token")+"&"); 
     basestring = bs.ToString(); 

     StringBuilder p = new StringBuilder(); 
     p.Append("oauth_callback=oob"); 
     p.Append("&oauth_consumer_key="); 
     p.Append(ConsumerKey); 
     p.Append("oauth_nonce="); 
     p.Append(nonce); 
     p.Append("&oauth_signature_method=HMAC-SHA1"); 
     p.Append("&oauth_timestamp="); 
     p.Append(timestamp); 

     string paramers = UrlHelper.Encode(p.ToString()); 

     basestring += paramers; 
     Console.WriteLine("Basestring: " + basestring); 



     System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); 

     string key = Secret + "&"; 
     Console.WriteLine("Key: " + key); 

     byte[] keyByte = encoding.GetBytes(key); 

     //--create message to encrypt 
     byte[] messageBytes = encoding.GetBytes(basestring); 

     //--encrypt message using hmac-sha1 with the provided key 
     HMACSHA1 hmacsha1 = new HMACSHA1(keyByte); 
     byte[] hashmessage = hmacsha1.ComputeHash(messageBytes); 

     //--signature 
     string signature = ByteToString(hashmessage); 
     Console.WriteLine("Signature: " + signature); 

     Console.WriteLine("Final Request: " + requesturl + "&oauth_signature=" + signature); 


     Console.ReadKey(true); 



    } 
    public static string ByteToString(byte[] buff) 
    { 
     string sbinary = ""; 

     for (int i = 0; i < buff.Length; i++) 
     { 
      sbinary += buff[i].ToString("X2"); // hex format 
     } 
     return (sbinary); 
    } 
} 

Khi tôi duyệt đến url ứng dụng này cung cấp cho tôi, tôi nhận được phản hồi sau đây:

oauth_problem=signature_invalid&debug_sbs=GET&http%3A%2F%2Fwww.flickr.com%2Fservices%2Foauth%2Frequest_token&oauth_callback%3Dhttp%253A%252F%252Fwww.google.be%26oauth_consumer_key%3D1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a%26oauth_nonce%3D27504343%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1329469580 

Dường như chữ ký của tôi cho yêu cầu không hợp lệ.

Tôi hy vọng ai đó có thể giúp tôi có được chữ ký phù hợp cho các yêu cầu này.

Tôi biết có một thư viện FlickNet đã làm công việc khó khăn cho hầu hết các nhà phát triển nhưng tôi nghĩ rằng nó có thể hữu ích để có được điều này làm việc quá. Tôi đã xem xét mã nguồn của FlickrNet nhưng không tìm thấy sự yên bình cuối cùng để hoàn thành mã này.

Hãy cho tôi biết nếu bạn có thể giúp tôi. Nó sẽ rất tuyệt vời!

Cảm ơn!

+0

Lưu ý với chính tôi: Thông tin thêm về xác thực oauth có thể tìm thấy tại đây: http://hueniverse.com/oauth/guide/authentication/ Tôi sẽ xem xét điều này ngay khi có thể :) – ThdK

Trả lời

9

Ok, cuối cùng tôi đã tự tìm được câu trả lời. Dưới đây là một vài điều bạn cần lưu ý khi ký yêu cầu cho oauth.

  1. chữ ký phải được mã hóa với HMAC-SHA1 sử dụng basestring (xem nr.2) dưới dạng văn bản được mã hóa và clientsecret và token_secret (nếu có) (xem nr. 3)
  2. basestring = [HttpMethod] & [FlickrAPIEndpoint] & [Parameters]
  3. chính cho yêu cầu oauth_token = [ApiSecret] & (hoặc key = [ApiSecret] & [oauth_token_secret] cho yêu cầu access_token)

QUAN TRỌNG: FlickrAPIEndPoint và Tham số phải được UrlEncoded (trong hai phần!) Tôi đã sử dụng một lớp riêng biệt cho mã hóa vì phương thức HttpUtility.UrlEncode sử dụng mã hóa chữ thường trong khi mã hóa chữ hoa nên được sử dụng.

QUAN TRỌNG: Tham số phải theo thứ tự bảng chữ cái!

Đây là mã cho ứng dụng bảng điều khiển sẽ tạo yêu cầu đã ký cho mã thông báo yêu cầu và bí mật mã thông báo yêu cầu.

class Program 
{ 
    private static string Secret = "9dcc18a121e9a02e"; 
    private static string ConsumerKey = "3aafc63ec6b05f3f9a9ff3a1c35ce541"; 
    private static string request_token = ""; 

    static void Main(string[] args) 
    { 

     string requestString = "http://www.flickr.com/services/oauth/request_token"; 

     //generate a random nonce and a timestamp 
     Random rand = new Random(); 
     string nonce = rand.Next(999999).ToString(); 
     string timestamp = GetTimestamp(); 

     //create the parameter string in alphabetical order 
     string parameters = "oauth_callback=" + UrlHelper.Encode("http://www.example.com"); 
     parameters += "&oauth_consumer_key=" + ConsumerKey; 
     parameters += "&oauth_nonce=" + nonce; 
     parameters += "&oauth_signature_method=HMAC-SHA1"; 
     parameters += "&oauth_timestamp=" + timestamp; 
     parameters += "&oauth_version=1.0"; 

     //generate a signature base on the current requeststring and parameters 
     string signature = generateSignature("GET", requestString, parameters); 

     //add the parameters and signature to the requeststring 
     string url = requestString + "?" + parameters + "&oauth_signature=" + signature; 

     //test the request 
     WebClient web = new WebClient(); 
     string result = web.DownloadString(url); 

     Console.WriteLine("Flickr Response: "); 
     Console.WriteLine(result); //contains the oauth_token and the oauth_token_secret 
     Console.ReadKey(true); 

    } 

    private static string generateSignature(string httpMethod, string ApiEndpoint, string parameters) 
    { 
     //url encode the API endpoint and the parameters 

     //IMPORTANT NOTE: 
     //encoded text should contain uppercase characters: '=' => %3D !!! (not %3d) 
     //the HtmlUtility.UrlEncode creates lowercase encoded tags! 
     //Here I use a urlencode class by Ian Hopkins 
     string encodedUrl = UrlHelper.Encode(ApiEndpoint); 
     string encodedParameters = UrlHelper.Encode(parameters); 

     //generate the basestring 
     string basestring = httpMethod + "&" + encodedUrl + "&"; 
     parameters = UrlHelper.Encode(parameters); 
     basestring = basestring + parameters; 

     //hmac-sha1 encryption: 

     System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); 

     //create key (request_token can be an empty string) 
     string key = Secret + "&" + request_token; 
     byte[] keyByte = encoding.GetBytes(key); 

     //create message to encrypt 
     byte[] messageBytes = encoding.GetBytes(basestring); 

     //encrypt message using hmac-sha1 with the provided key 
     HMACSHA1 hmacsha1 = new HMACSHA1(keyByte); 
     byte[] hashmessage = hmacsha1.ComputeHash(messageBytes); 

     //signature is the base64 format for the genarated hmac-sha1 hash 
     string signature = System.Convert.ToBase64String(hashmessage); 

     //encode the signature to make it url safe and return the encoded url 
     return UrlHelper.Encode(signature); 

    } 

    //generator of unix epoch time 
    public static String GetTimestamp() 
    { 
     int epoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; 
     return epoch.ToString(); 
    } 

} 

UrlHelper lớp bằng Ian Hopkins sử dụng để mã hóa url

/// <summary> 
    /// URL encoding class. Note: use at your own risk. 
    /// Written by: Ian Hopkins (http://www.lucidhelix.com) 
    /// Date: 2008-Dec-23 
    /// (Ported to C# by t3rse (http://www.t3rse.com)) 
    /// </summary> 
    public class UrlHelper 
    { 
     public static string Encode(string str) 
     { 
      var charClass = String.Format("0-9a-zA-Z{0}", Regex.Escape("-_.!~*'()")); 
      return Regex.Replace(str, 
       String.Format("[^{0}]", charClass), 
       new MatchEvaluator(EncodeEvaluator)); 
     } 
    public static string EncodeEvaluator(Match match) 
    { 
     return (match.Value == " ") ? "+" : String.Format("%{0:X2}", Convert.ToInt32(match.Value[0])); 
    } 

    public static string DecodeEvaluator(Match match) 
    { 
     return Convert.ToChar(int.Parse(match.Value.Substring(1), System.Globalization.NumberStyles.HexNumber)).ToString(); 
    } 

    public static string Decode(string str) 
    { 
     return Regex.Replace(str.Replace('+', ' '), "%[0-9a-zA-Z][0-9a-zA-Z]", new MatchEvaluator(DecodeEvaluator)); 
    } 
} 
+0

giúp rất nhiều, cảm ơn ! –

1

Bạn có viết điều này từ đầu không? Nếu vậy, bạn không nên. Sử dụng http://flickrnet.codeplex.com/ để thay thế. Thư viện này đã thực hiện việc nâng hạng nặng cho bạn.

+1

Tôi đã tải về thư viện flickrnet nhưng tôi muốn hiểu những gì nó làm. Bởi vì đối với một ứng dụng rất nhỏ, nơi tôi chỉ cần thực hiện một hoặc chỉ một vài yêu cầu để api Flickr, tôi nghĩ rằng tôi có thể viết này bản thân mình. (Tôi đã làm tương tự cho Facebook API năm ngoái) – ThdK

+1

@ThomasDekiere Mã nguồn nằm ngay trên codeplex để bạn có thể xem nó hoạt động bằng cách tải xuống và duyệt nguồn. – Jeff

+0

Ok có vẻ như tôi cần nghiên cứu thêm trước. Tôi tìm kiếm trong mã nguồn của flickrnet mà không cần tìm thông tin tôi cần. Bây giờ, Sau khi đọc rất nhiều ví dụ trong tất cả các loại ngôn ngữ lập trình, tôi đã tạo ra một ứng dụng giao diện điều khiển mô phỏng việc tạo ra một yêu cầu cho api flickr. Nhưng tôi nhận được thông báo chữ ký không hợp lệ. Tôi đã tạo một câu hỏi mới ở đây với tất cả thông tin và mã tôi có: http://stackoverflow.com/questions/9330004/invalid-signature-for-signing-requests-to-the-flickr-api-simulation-in -console – ThdK

Các vấn đề liên quan