2012-02-17 12 views
5

Estoy intentando autenticar a la API de Flickr para una aplicación de demostración que quiero hacer por mí mismo. Luego extenderé esta aplicación con nuevas características que aprenderé de las API de Flick.firma no válida para solicitudes de firma a la API de Flickr (simulación en la consola)

Así que esto es algo con lo que quiero jugar. Pero ahora tengo algunos problemas para obtener un token de solicitud.

Estoy siguiendo la documentación de autenticación de Flickr aquí: Flickr Authentication
y también me encontré con este Mathlabscript: Flickr API with OAuth-based user authentication

Así que basado en estas fuentes que tengo ahora la siguiente aplicación de consola:

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

Cuando busco la URL que me dan estas aplicaciones, obtengo la siguiente respuesta:

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 

Parece que mi firma para la solicitud no es válida.

Espero que alguien pueda ayudarme a obtener la firma correcta para estas solicitudes.

Yo sé que hay una Biblioteca FlickNet que ya hizo el trabajo duro para la mayoría de los desarrolladores, pero creo que puede ser útil para conseguir este trabajo también. Miré el código fuente de FlickrNet pero no encontré la paz final para completar este código.

Avísame si me puedes ayudar. ¡Sería genial!

Gracias!

+0

Nota para mí: puede encontrar más información acerca de la autenticación oauth aquí: http://hueniverse.com/oauth/guide/authentication/ Lo veré tan pronto como pueda :) – ThdK

Respuesta

9

Ok, finalmente encontré la respuesta yo mismo. Aquí hay algunas cosas que debe tener en cuenta al firmar solicitudes de Oauth.

  1. firma debe ser encriptado con HMAC-SHA1 usando la cadena base (véase el n º 2) como texto a cifrar y la clientsecret y la token_secret (si lo tiene) (ver nr. 3)
  2. basestring = [HTTPMethod] & [FlickrAPIEndpoint] & [Parámetros]
  3. Key para la solicitud oauth_token = [ApiSecret] & (o la tecla = [ApiSecret] & [oauth_token_secret] para la petición señal_acceso)

IMPORTANTE: (en dos partes) FlickrAPIEndPoint y parámetros deben ser urlencoded He utilizado una clase separada para la codificación ya que el método HttpUtility.UrlEncode utiliza la codificación en minúsculas, mientras que la codificación mayúsculas se debe utilizar.

IMPORTANTE: ¡Los parámetros deben estar en orden alfabético!

Aquí está el código de una aplicación de consola que va a crear una solicitud firmada por un token de solicitud y una solicitud secreta del token.

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

} 

clase UrlHelper por Ian Hopkins utiliza para la codificación 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

ayuda mucho, gracias ! –

1

¿Está escribiendo esto desde el principio? Si es así, no deberías. Use http://flickrnet.codeplex.com/ en su lugar. Esta biblioteca ya ha hecho el trabajo pesado por ti.

+1

He descargado la biblioteca flickrnet pero yo quería entender lo que hace. Porque para una aplicación muy pequeña, donde solo necesito hacer una o solo unas pocas solicitudes a la API de Flickr, pensé que podría escribir esto yo mismo. (Hice lo mismo para la API de Facebook el año pasado) – ThdK

+1

@ThomasDekiere El código fuente está allí en codeplex para que pueda ver lo que hace al descargarlo y explorar la fuente. – Jeff

+0

Ok, parece que primero necesité un poco más de investigación. Busqué en el código fuente de flickrnet sin encontrar la información que necesitaba. Ahora, después de leer muchos ejemplos en todo tipo de lenguajes de programación, he creado una aplicación de consola que simula la creación de una solicitud a la API de flickr. Pero recibo el mensaje de firma no válido. He creado una nueva pregunta aquí con toda la información y el código que tengo: http://stackoverflow.com/questions/9330004/invalid-signature-for-signing-requests-to-the-flickr-api-simulation-in -console – ThdK

Cuestiones relacionadas