对 Flickr API 的请求签名无效(控制台中的模拟) [英] Invalid signature for signing requests to the Flickr API (simulation in console)

查看:14
本文介绍了对 Flickr API 的请求签名无效(控制台中的模拟)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过 Flickr API 验证我想为自己制作的演示应用程序.然后,我将使用 Flick API 的新功能扩展此应用程序.

所以这只是我想玩的东西.但是现在我在获取请求令牌时遇到了一些麻烦.

我在此处关注 Flickr 身份验证文档:Flickr 身份验证
我还发现了这个 Mathlabscript:具有基于 OAuth 的用户身份验证的 Flickr API

因此,基于这些来源,我现在拥有以下控制台应用程序:

class 程序{私有静态字符串 Secret = "2b2b2b2b2b2b2b2b2b";私有静态字符串 ConsumerKey = "1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a";静态无效主(字符串 [] args){随机 rand = new Random();字符串随机数 = rand.Next(9999999).ToString();字符串时间戳 = ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString();Console.WriteLine("Nonce: " + nonce);Console.WriteLine("时间戳:" + 时间戳);Console.WriteLine("ConsumerKey: " + ConsumerKey);Console.WriteLine("AppSecret: " + Secret);//请求地址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.附加(时间戳);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);//基本网址字符串基串;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(时间戳);字符串参数 = UrlHelper.Encode(p.ToString());基串 += 参数;Console.WriteLine("Basestring: " + basestring);System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();字符串键 = 秘密 + "&";Console.WriteLine("键:" + 键);byte[] keyByte = encoding.GetBytes(key);//--创建要加密的消息byte[] messageBytes = encoding.GetBytes(basestring);//--使用 hmac-sha1 和提供的密钥加密消息HMACSHA1 hmacsha1 = 新 HMACSHA1(keyByte);byte[] hashmessage = hmacsha1.ComputeHash(messageBytes);//- 签名字符串签名 = ByteToString(hashmessage);Console.WriteLine("签名:" + 签名);Console.WriteLine("最终请求:" + requesturl + "&oauth_signature=" + 签名);Console.ReadKey(true);}公共静态字符串 ByteToString(byte[] buff){字符串 sbinary = "";for (int i = 0; i < buff.Length; i++){sbinary += buff[i].ToString("X2");//十六进制格式}返回(二进制);}}

当我浏览到这个应用程序给我的 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 的源代码,但没有找到完成此代码的最终和平.

如果你能帮助我,请告诉我.那就太好了!

谢谢!

解决方案

好吧,我终于自己找到了答案.在签署 oauth 请求时,您必须牢记以下几点.

  1. 签名必须使用 HMAC-SHA1 加密,使用 basestring(参见 nr.2)作为要加密的文本以及 clientsecret 和 token_secret(如果有的话)(参见 nr.3)
  2. basestring = [HttpMethod]&[FlickrAPIEndpoint]&[Parameters]
  3. 请求的密钥 oauth_token = [ApiSecret]&(或 key = [ApiSecret]&[Oauth_token_secret] 用于请求 access_token)

重要提示:FlickrAPIEndPoint 和参数必须是 UrlEncoded(分为两部分!)我使用了一个单独的类进行编码,因为 HttpUtility.UrlEncode 方法使用小写编码,而应该使用大写编码.

重要提示:参数必须按字母顺序排列!

这是控制台应用程序的代码,它将为请求令牌和请求令牌密钥创建签名请求.

class 程序{私有静态字符串 Secret = "9dcc18a121e9a02e";私有静态字符串 ConsumerKey = "3aafc63ec6b05f3f9a9ff3a1c35ce541";私有静态字符串 request_token = "";静态无效主(字符串 [] args){string requestString = "http://www.flickr.com/services/oauth/request_token";//生成一个随机数和时间戳随机 rand = new Random();字符串随机数 = rand.Next(999999).ToString();字符串时间戳 = GetTimestamp();//按字母顺序创建参数字符串字符串参数 = "oauth_callback=" + UrlHelper.Encode("http://www.example.com");参数 += "&oauth_consumer_key=" + ConsumerKey;参数 += "&oauth_nonce=" + nonce;参数 += "&oauth_signature_method=HMAC-SHA1";参数 += "&oauth_timestamp=" + 时间戳;参数 += "&oauth_version=1.0";//根据当前请求字符串和参数生成签名string signature = generateSignature("GET", requestString, parameters);//将参数和签名添加到请求字符串中字符串 url = requestString + "?"+ 参数 + "&oauth_signature=" + 签名;//测试请求WebClient web = new WebClient();字符串结果 = web.DownloadString(url);Console.WriteLine("Flickr 响应:");Console.WriteLine(result);//包含oauth_token和oauth_token_secretConsole.ReadKey(true);}私有静态字符串 generateSignature(string httpMethod, string ApiEndpoint, string parameters){//url对API端点和参数进行编码//重要的提示://编码文本应包含大写字符:'=' =>%3D !!!(不是 %3d )//HtmlUtility.UrlEncode 创建小写编码的标签!//这里我使用了 Ian Hopkins 的 urlencode 类string encodingUrl = UrlHelper.Encode(ApiEndpoint);string encodingParameters = UrlHelper.Encode(parameters);//生成基串字符串 basestring = httpMethod + "&"+ 编码网址 + "&";参数 = UrlHelper.Encode(参数);basestring = basestring + 参数;//hmac-sha1 加密:System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();//创建key(request_token可以是空字符串)字符串键 = 秘密 + "&"+ request_token;byte[] keyByte = encoding.GetBytes(key);//创建要加密的消息byte[] messageBytes = encoding.GetBytes(basestring);//使用hmac-sha1和提供的密钥加密消息HMACSHA1 hmacsha1 = 新 HMACSHA1(keyByte);byte[] hashmessage = hmacsha1.ComputeHash(messageBytes);//签名是生成的hmac-sha1哈希的base64格式字符串签名 = System.Convert.ToBase64String(hashmessage);//对签名进行编码以使其 url 安全并返回编码后的 url返回 UrlHelper.Encode(signature);}//unix纪元时间生成器公共静态字符串 GetTimestamp(){int epoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;返回纪元.ToString();}}

Ian Hopkins 的 UrlHelper 类用于 url 编码

////<摘要>///URL 编码类.注意:使用风险自负.///作者:伊恩霍普金斯 (http://www.lucidhelix.com)///日期:2008 年 12 月 23 日///(由 t3rse (http://www.t3rse.com) 移植到 C#)///</总结>公共类 UrlHelper{公共静态字符串编码(字符串 str){var charClass = String.Format("0-9a-zA-Z{0}", Regex.Escape("-_.!~*'()"));返回 Regex.Replace(str,String.Format("[^{0}]", charClass),新的 MatchEvaluator(EncodeEvaluator));}公共静态字符串 EncodeEvaluator(匹配匹配){返回 (match.Value == " ") ?"+" : String.Format("%{0:X2}", Convert.ToInt32(match.Value[0]));}公共静态字符串 DecodeEvaluator(匹配匹配){return Convert.ToChar(int.Parse(match.Value.Substring(1), System.Globalization.NumberStyles.HexNumber)).ToString();}公共静态字符串解码(字符串str){return Regex.Replace(str.Replace('+', ' '), "%[0-9a-zA-Z][0-9a-zA-Z]", new MatchEvaluator(DecodeEvaluator));}}

I'm trying to authenticate to the Flickr API for a demo application I want to make for myself. Then i will extend this app with new features that i'll learn of the Flick API's.

So this is just something i want to play with. But now I have some trouble in getting a request token.

I'm following the Flickr Authentication documentation here: Flickr Authentication
And i also found this Mathlabscript: Flickr API with OAuth-based user authentication

So based on these sources i have now the following console application:

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

When i browse to the url this applications give me, i get the following response:

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

It seems that my signature for the request is invalid.

I hope someone can help me get the right signature for these requests.

I know there is a FlickNet Library that already did the hard work for most of the developers but i think it can be useful to get this working too. I looked into the source code of FlickrNet but didn't find the final peace to complete this code.

Let me know if you can help me. It would be so great!

Thanks!

解决方案

Ok, I finally found the answer myself. Here are a few things you have to keep in mind when signing requests for oauth.

  1. signature must be encrypted with HMAC-SHA1 using the basestring(see nr.2) as text to be encrypted and the clientsecret and the token_secret (if you have one) (see nr. 3)
  2. basestring = [HttpMethod]&[FlickrAPIEndpoint]&[Parameters]
  3. Key for request oauth_token = [ApiSecret]& (or key = [ApiSecret]&[Oauth_token_secret] for request access_token)

IMPORTANT: FlickrAPIEndPoint and Parameters must be UrlEncoded (in two parts!) I have used a separate class for the encoding because the HttpUtility.UrlEncode method uses lowercase encoding while the uppercase encoding should be used.

IMPORTANT: Parameters must be in alphabetical order!

Here's the code for a console application that will create a signed request for a request token and a request token secret.

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 class by Ian Hopkins used for the url encoding

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

这篇关于对 Flickr API 的请求签名无效(控制台中的模拟)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆