Неверная подпись для подписания запросов к Flickr API (симуляция в консоли) - PullRequest
5 голосов
/ 17 февраля 2012

Я пытаюсь пройти аутентификацию в Flickr API для демонстрационного приложения, которое хочу создать для себя.Затем я дополню это приложение новыми функциями, которые я узнаю о API Flick.

Так что это просто то, с чем я хочу поиграть.Но теперь у меня возникли проблемы с получением токена запроса.

Я следую документации по аутентификации Flickr здесь: Аутентификация Flickr
И я также нашел этот Mathlabscript: API Flickr с аутентификацией пользователя на основе OAuth

Итак, на основании этих источников у меня теперь есть следующее консольное приложение:

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

Когда я просматриваю URL, который дают мне эти приложения, я получаю следующий ответ:

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

Кажется, моя подпись под запросом недействительна.

Я надеюсь, что кто-то может помочь мне получить правильную подпись для этих запросов.

Я знаю, что есть библиотека FlickNet, которая уже сделала тяжелую работу для большинства разработчиков, но я думаю, что это может бытьполезно, чтобы это работало тоже.Я изучил исходный код FlickrNet, но не нашел окончательного решения для завершения этого кода.

Дайте мне знать, если вы можете мне помочь.Это было бы так здорово!

Спасибо!

Ответы [ 2 ]

9 голосов
/ 21 февраля 2012

Хорошо, я наконец нашел ответ сам.Вот несколько вещей, которые вы должны иметь в виду при подписании запросов на oauth.

  1. подпись должна быть зашифрована с помощью HMAC-SHA1 с использованием базовой строки (см. П.2) в качестве текста, который необходимо зашифровать, иclientsecret и token_secret (если есть) (см. номер 3)
  2. basestring = [HttpMethod] & [FlickrAPIEndpoint] & [Parameters]
  3. Ключ для запроса oauth_token = [ApiSecret] &(или ключ = [ApiSecret] & [Oauth_token_secret] для запроса access_token)

ВАЖНО: FlickrAPIEndPoint и Parameters должны быть UrlEncoded (из двух частей!) Я использовал отдельный класс для кодирования, поскольку HttpUtilityМетод .UrlEncode использует строчную кодировку, в то время как должна использоваться прописная кодировка.

ВАЖНО: параметры должны быть в алфавитном порядке!

Вот код консольного приложения, которое создаст подписанный запрос на токен запроса и секрет токена запроса.

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 Яна Хопкинса, используемый для кодирования 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));
    }
} 
1 голос
/ 16 февраля 2012

Вы пишете это с нуля? Если это так, вы не должны. Вместо этого используйте http://flickrnet.codeplex.com/. Эта библиотека уже сделала тяжелую работу за вас.

...