Implementasi OAuth berkaki 2 di C#

Saya mencoba menerapkan otentikasi OAuth berkaki dua, sehingga saya bisa membuat Pengguna di situs web. Saya berhasil membuat kode Ruby yang melakukan tugas itu, tetapi saya perlu mengonversinya ke C#.

Saya mendapatkan kesalahan 401 saat membuat POST terakhir di C#, tetapi kodenya hampir sama. Aku menjadi gila di sini. Bisakah seseorang masuk dan membantu saya mengetahui apa yang salah dengan kode saya?

Rubi

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

Terima kasih,


person Daniel    schedule 08.09.2011    source sumber
comment
Apakah Anda pernah bisa membuat ini berfungsi? Saya perlu melakukan hal serupa sehingga saya dapat melindungi beberapa tindakan pengontrol MVC melalui OAUTH.   -  person AlexGad    schedule 24.09.2011
comment
Ya, tapi ini adalah implementasi klien. Saya perlu terhubung dengan layanan OAuth yang ada. Apakah ini juga yang Anda butuhkan? Saya akan memposting solusinya nanti.   -  person Daniel    schedule 26.09.2011


Jawaban (1)


Saya tidak yakin apakah jawabannya masih bermanfaat bagi Anda atau tidak. Ini adalah versi implementasi saya yang bisa diterapkan.

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

Berikut ini cara menggunakan HttpClient untuk memanggil layanan jarak jauh.

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);
person wannadream    schedule 20.06.2019