C# 中的 2-legged OAuth 实现 [英] 2-legged OAuth implementation in C#

查看:50
本文介绍了C# 中的 2-legged OAuth 实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实施两条腿的 OAuth 身份验证,以便我可以在网站上创建用户.我设法编写了执行该任务的 ruby​​ 代码,但我需要将其转换为 C#.

I'm trying to implement a two-legged OAuth authentication, so I can get to create a User on a website. I managed to craft this ruby code that performs that task, but I need to convert it to C#.

在 C# 中进行最后一次 POST 时出现 401 错误,但代码实际上是相同的.我快疯了.有人可以加入并帮助我知道我的代码有什么问题吗?

I'm getting a 401 error when making the last POST in C#, but the code is practically the same. I'm getting crazy here. Can someone jump in and help me know what's wrong with my code?

红宝石

consumer = OAuth::Consumer.new(KEY, SECRET, :http_method => :post)
# response = consumer.request(:get, "#{SITE}/oauth/request_token.json") 
# request_token_hash = JSON.parse(response.body) 
# puts request_token_hash
access_token = OAuth::AccessToken.new consumer
user = { 
     "user[name]" => 'John' 
}
response = access_token.post("#{SITE}/users.json", user) 
user_hash = JSON.parse(response.body)
puts user_hash

C#

string consumerKey = "KEY";
            string consumerSecret = "SECRET";
            Uri uri = new Uri("#{SITE}/oauth/request_token.json");

            var oAuth = new OAuthBase(); // this class generates signatures
            string nonce = oAuth.GenerateNonce();
            string timeStamp = oAuth.GenerateTimeStamp();
            string outURL;
            string queryString;

            string sig = oAuth.GenerateSignature(
                uri,
                consumerKey,
                consumerSecret,
                string.Empty,
                string.Empty,
                "POST",
                timeStamp,
                nonce,
                OAuthBase.SignatureTypes.HMACSHA1,
                out outURL,
                out queryString);


            sig = HttpUtility.UrlEncode(sig);

            var sb = new StringBuilder(uri.ToString());
            sb.AppendFormat("?oauth_consumer_key={0}&", consumerKey);
            sb.AppendFormat("oauth_nonce={0}&", nonce);
            sb.AppendFormat("oauth_timestamp={0}&", timeStamp);
            sb.AppendFormat("oauth_signature_method={0}&", "HMAC-SHA1");
            sb.AppendFormat("oauth_version={0}&", "1.0");
            sb.AppendFormat("oauth_signature={0}", sig);

            var tokenRequest = (HttpWebRequest)WebRequest.Create(sb.ToString());
            tokenRequest.Method = "POST";
            var response = tokenRequest.GetResponse().GetResponseStream();
            if (response != null)
            {
                var responseReader = new StreamReader(response);
                var requestToken = JsonConvert.DeserializeObject<RequestToken>(responseReader.ReadToEnd());
                System.Diagnostics.Debug.WriteLine("REQUEST TOKEN: " + requestToken.token.oauth_token);

                // EVERYTHING IS OK UNTIL HERE

                // Creating user
                nonce = oAuth.GenerateNonce();
                timeStamp = oAuth.GenerateTimeStamp();

                var usersUri = new Uri("#{SITE}/users.json");

                // Generate signature
                string userSig = oAuth.GenerateSignature(
                userUri,
                consumerKey,
                consumerSecret,
                requestToken.token.oauth_token,
                requestToken.token.oauth_token_secret,
                "POST",
                timeStamp,
                nonce,
                OAuthBase.SignatureTypes.HMACSHA1,
                out outURL,
                out queryString);

                userSig = HttpUtility.UrlEncode(userSig);

                // Generate request URL
                sb = new StringBuilder(userUri.ToString());
                sb.AppendFormat("?oauth_consumer_key={0}&", consumerKey);
                sb.AppendFormat("oauth_nonce={0}&", nonce);
                sb.AppendFormat("oauth_timestamp={0}&", timeStamp);
                sb.AppendFormat("oauth_signature_method={0}&", "HMAC-SHA1");
                sb.AppendFormat("oauth_version={0}&", "1.0");
                sb.AppendFormat("oauth_token={0}&", requestToken.token.oauth_token);
                sb.AppendFormat("oauth_signature={0}&", userSig);
                sb.Append("user[name]=John");


                // Prepare web request...
                var myRequest = (HttpWebRequest)WebRequest.Create(sb.ToString());
                myRequest.Method = "POST";

                // Get response and read it
                var reader = new StreamReader(myRequest.GetResponse().GetResponseStream()); // THROWS AN UNAUTHORIZED EXCEPTION (401 Status Error)
                System.Diagnostics.Debug.WriteLine("RESPONSE USER: " + reader.ReadToEnd());

谢谢,

推荐答案

我不确定答案是否仍然对您有帮助.这是我的实现的可行版本.

I am not sure if the answer is still helpful for you or not. Here is a workable version of mine implementation.

public static string GetOAuth_1_TwoLeggedHeaderString(string url, string httpMethod
    , string consumerKey, string consumerSecret)
{
    var timeStamp = ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString();
    var nonce = Guid.NewGuid().ToString("D");
    var signatureMethod = "HMAC-SHA1";
    var version = "1.0";

    var signatureBase = Encode(httpMethod.ToUpper()) + "&";
    signatureBase += Encode(url.ToLower()) + "&";
    signatureBase += Encode("oauth_consumer_key=" + Encode(consumerKey) + "&" +
        "oauth_nonce=" + Encode(nonce) + "&" +
        "oauth_signature_method=" + Encode(signatureMethod) + "&" +
        "oauth_timestamp=" + Encode(timeStamp) + "&" +
        "oauth_version=" + Encode(version));

    string signatureString;

    using (HMACSHA1 crypto = new HMACSHA1())
    {
        string key = Encode(consumerSecret) + "&";
        crypto.Key = Encoding.ASCII.GetBytes(key);
        string hash = Convert.ToBase64String(crypto.ComputeHash(Encoding.ASCII.GetBytes(signatureBase)));
        crypto.Clear();

        signatureString = hash;
    }

    string SimpleQuote(string s) => '"' + s + '"';
    return
        "OAuth " +
        "oauth_consumer_key=" + SimpleQuote(Encode(consumerKey)) + ", " +
        "oauth_signature_method=" + SimpleQuote(Encode(signatureMethod)) + ", " +
        "oauth_timestamp=" + SimpleQuote(Encode(timeStamp)) + ", " +
        "oauth_nonce=" + SimpleQuote(Encode(nonce)) + ", " +
        "oauth_version=" + SimpleQuote(Encode(version)) + ", " +
        "oauth_signature=" + SimpleQuote(Encode(signatureString));
}

private static string Encode(string input)
{
    if (string.IsNullOrEmpty(input))
        return string.Empty;

    return Encoding.ASCII.GetString(EncodeToBytes(input, Encoding.UTF8));
}

private static byte[] EncodeToBytes(string input, Encoding enc)
{
    if (string.IsNullOrEmpty(input))
        return new byte[0];

    byte[] inbytes = enc.GetBytes(input);

    // Count unsafe characters
    int unsafeChars = 0;
    char c;
    foreach (byte b in inbytes)
    {
        c = (char)b;

        if (NeedsEscaping(c))
            unsafeChars++;
    }

    // Check if we need to do any encoding
    if (unsafeChars == 0)
        return inbytes;

    byte[] outbytes = new byte[inbytes.Length + (unsafeChars * 2)];
    int pos = 0;

    for (int i = 0; i < inbytes.Length; i++)
    {
        byte b = inbytes[i];

        if (NeedsEscaping((char)b))
        {
            outbytes[pos++] = (byte)'%';
            outbytes[pos++] = (byte)IntToHex((b >> 4) & 0xf);
            outbytes[pos++] = (byte)IntToHex(b & 0x0f);
        }
        else
            outbytes[pos++] = b;
    }

    return outbytes;
}

private static bool NeedsEscaping(char c)
{
    return !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')
            || c == '-' || c == '_' || c == '.' || c == '~');
}

private static char IntToHex(int n)
{
    if (n < 0 || n >= 16)
        throw new ArgumentOutOfRangeException("n");

    if (n <= 9)
        return (char)(n + (int)'0');
    else
        return (char)(n - 10 + (int)'A');
}

这里是如何使用HttpClient调用远程服务.

Here is how to use HttpClient to call remote service.

string url = "[Remote Service Endpoint URL]";

// Call Drupal API to create new node
httpClient.DefaultRequestHeaders.Remove("Authorization");
httpClient.DefaultRequestHeaders.Add("Authorization"
    , WebServiceUtils.GetOAuth_1_TwoLeggedHeaderString(url, "POST", "[Consumer Key]", "[Consumer Secret]"));

const string Format = @"{
    ""type"": ""sharing"",
    ""title"": ""test"",
    ""created"": ""12323233"",
    ""body"": {
        ""und"": {
            ""0"": {
                ""value"": ""test""
            }
        }
    },
    ""name"": ""test""
}";
var bodyContent = new StringContent(Format, Encoding.UTF8, "application/json");
var result = await httpClient.PostAsync(url, bodyContent);

这篇关于C# 中的 2-legged OAuth 实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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