2012-02-17 19 views
5

Sto provando ad autenticare l'API di Flickr per un'applicazione demo che voglio realizzare personalmente. Quindi estenderò questa app con nuove funzionalità che apprenderò delle API di Flick.Firma non valida per la firma delle richieste all'API di Flickr (simulazione in console)

Quindi questo è solo qualcosa con cui voglio giocare. Ma ora ho qualche problema nell'ottenere un token di richiesta.

Sto seguendo la documentazione Flickr autenticazione qui: Flickr Authentication
E ho trovato anche questo Mathlabscript: Flickr API with OAuth-based user authentication

Quindi, sulla base di queste fonti che ho adesso la seguente applicazione di console:

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

Quando cerco l'URL che mi danno queste applicazioni, ottengo la seguente risposta:

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 

Sembra che la mia firma per la richiesta non sia valida.

Spero che qualcuno possa aiutarmi a ottenere la firma giusta per queste richieste.

So che esiste una libreria FlickNet che ha già svolto il duro lavoro per la maggior parte degli sviluppatori, ma penso che possa essere utile far funzionare anche questo. Ho esaminato il codice sorgente di FlickrNet ma non ho trovato la pace definitiva per completare questo codice.

Fammi sapere se puoi aiutarmi. Sarebbe fantastico!

Grazie!

+0

Nota per me: ulteriori informazioni sull'autenticazione oauth possono essere trovate qui: http://hueniverse.com/oauth/guide/authentication/ Vedrò questo appena possibile :) – ThdK

risposta

9

Ok, ho finalmente trovato la risposta da solo. Ecco alcune cose che devi tenere a mente quando firmi le richieste di oauth.

  1. firma deve essere criptato con HMAC-SHA1 utilizzando il basestring (vedi nr.2) come testo da criptare e la clientsecret e il token_secret (se ne avete uno) (vedi n. 3)
  2. basestring = [HttpMethod] & [FlickrAPIEndpoint] & [parametri]
  3. chiave per la richiesta oauth_token = [ApiSecret] & (o il tasto = [ApiSecret] & [oauth_token_secret] per la richiesta access_token)

IMPORTANTE: FlickrAPIEndPoint e Parametri devono essere UrlEncoded (in due parti!) Ho usato una classe separata per la codifica perché il metodo HttpUtility.UrlEncode utilizza la codifica minuscola mentre la codifica in maiuscolo deve essere utilizzata.

IMPORTANTE: i parametri devono essere in ordine alfabetico!

Ecco il codice per un'applicazione console che creerà una richiesta firmata per un token di richiesta e un token segreto di richiesta.

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

} 

classe UrlHelper da Ian Hopkins utilizzato per la codifica 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

aiuta molto, grazie ! –

1

Stai scrivendo questo da zero? Se è così, non dovresti. Utilizzare invece http://flickrnet.codeplex.com/. Questa libreria ha già fatto il pesante lavoro per te.

+1

Ho scaricato la libreria flickrnet ma volevo capire cosa fa. Perché per un'app molto piccola, in cui ho solo bisogno di fare una o solo alcune richieste per l'API di Flickr, ho pensato di poterlo scrivere io stesso. (Ho fatto lo stesso per l'API di Facebook l'anno scorso) – ThdK

+1

@ThomasDekiere Il codice sorgente è proprio lì su codeplex in modo da poter vedere cosa fa scaricandolo e sfogliando la fonte. – Jeff

+0

Ok, sembra che prima avessi bisogno di altre ricerche. Ho cercato nel codice sorgente di flickrnet senza trovare le informazioni di cui avevo bisogno. Ora, dopo aver letto molti esempi in tutti i tipi di linguaggi di programmazione, ho creato un'applicazione per console che simula la creazione di una richiesta per l'API di flickr. Ma ottengo il messaggio di firma non valido. Ho creato una nuova domanda qui con tutte le informazioni e il codice che ho: http://stackoverflow.com/questions/9330004/invalid-signature-for-signing-requests-to-the-flickr-api-simulation-in -console – ThdK

Problemi correlati