通过REST API c#使用共享密钥身份验证的Azure存储队列 [英] Azure Storage Queue via REST API c# using Shared Key Authentication

查看:0
本文介绍了通过REST API c#使用共享密钥身份验证的Azure存储队列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用REST API调用Azure存储队列,但遇到错误

在HTTP请求中找到的MAC签名 ‘UCiypkoySXueF4scXt+EqQESf5VXmAVLJUA93+3W10M=’不同于任何 计算签名。服务器使用以下字符串进行签名:‘POST 文本/纯文本

我的C#代码是

  var Client = new HttpClient();
        var RequestDateString = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);

        if (Client.DefaultRequestHeaders.Contains("x-ms-date"))
            Client.DefaultRequestHeaders.Remove("x-ms-date");
        Client.DefaultRequestHeaders.Add("x-ms-date", RequestDateString);


        var StorageAccountName = "storaxxxxxxxsnd";
        var StorageKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==";
        String urlPath = String.Format("{0}/messages", "splitator");
        Uri uri = new Uri(string.Format("https://{0}.queue.core.windows.net/", StorageAccountName) + urlPath);

        if (Client.DefaultRequestHeaders.Contains("Authorization"))
            Client.DefaultRequestHeaders.Remove("Authorization");

        var canonicalizedStringToBuild = string.Format("{0}
{1}", RequestDateString, $"/{StorageAccountName}/{uri.AbsolutePath.TrimStart('/')}");
        string signature;
        using (var hmac = new HMACSHA256(Convert.FromBase64String(StorageKey)))
        {
            byte[] dataToHmac = Encoding.UTF8.GetBytes(canonicalizedStringToBuild);
            signature = Convert.ToBase64String(hmac.ComputeHash(dataToHmac));
        }

        string authorizationHeader = string.Format($"{StorageAccountName}:" + signature);
        Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("SharedKey", authorizationHeader);
        Client.DefaultRequestHeaders.Accept.Clear();
        
        Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
        if (Client.DefaultRequestHeaders.Contains("x-ms-version"))
            Client.DefaultRequestHeaders.Remove("x-ms-version");

        Client.DefaultRequestHeaders.Add("x-ms-version", "2015-12-11");

        // if (httpMethod == HttpMethod.Delete || httpMethod == HttpMethod.Put)
        //  {
        //    if (Client.DefaultRequestHeaders.Contains("If-Match"))
        //       Client.DefaultRequestHeaders.Remove("If-Match");
        // Currently I'm not using optimistic concurrency :-(
        try
        {
            //Client.DefaultRequestHeaders.Add("If-Match", "*");
            var stringContent = new StringContent("TESTAUTH", Encoding.UTF8, "text/plain");
           var response= Client.PostAsync(uri, stringContent);
            var resu=response.Result;
            
        }
        catch(Exception ex)
        {

        }

我不确定我错过了什么。我尝试了各种组合,但都失败了。

我也尝试了微软推荐的StringToSign公式

I tried  using canonical headers too


        string signature;
     
        var stringTosign =  "POST
" + "
" + "
" + "1024" + "
" + "
" + "text/plain
" + "
" + "
" + "
" + "
" + "
" + "
" + dateInRfc1123Format + "/xxxxxx/splitator/messages";

       var hmac = new HMACSHA256(Convert.FromBase64String(accountKey));
       var headerval= accountName + ":" + Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringTosign)));
        Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("SharedKey", headerval);
        Client.DefaultRequestHeaders.Accept.Clear();
    

推荐答案

我修复了代码中的问题,现在它可以工作了。请试一试:

namespace ConsoleApp25
{
    class Program
    {
        static void Main(string[] args)
        {
            var Client = new HttpClient();
           
            var StorageAccountName = "yy1";
            var StorageKey = "xxxx";
            var apiversion = "2020-02-10";
            var queue_name = "myqueue2";
            String urlPath = String.Format("{0}/messages", queue_name);
            Uri uri = new Uri(string.Format("https://{0}.queue.core.windows.net/{1}", StorageAccountName, urlPath));

            //define a message to send
            string raw_message = "TESTAUTH is ok";

            //to send the message to the queue storage, the raw message must be formatted as below
            string queue_message = $"<QueueMessage><MessageText>{raw_message}</MessageText></QueueMessage>";

            //define the content type
            string content_type = "text/plain; charset=utf-8";

            //define date
            var RequestDateString = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);

            string StringToSign = String.Format("POST
"
                + "
" // content encoding
                + "
" // content language
                + queue_message.Length + "
" // content length
                + "
" // content md5
                + content_type +"
" // content type
                + "
" // date
                + "
" // if modified since
                + "
" // if match
                + "
" // if none match
                + "
" // if unmodified since
                + "
" // range
                + "x-ms-date:" + RequestDateString + "
x-ms-version:" + apiversion + "
" // headers
                + "/{0}/{1}/{2}", StorageAccountName, queue_name, "messages"); //url

            string auth = SignThis(StringToSign, StorageKey, StorageAccountName);

            //define authorization header
            if (Client.DefaultRequestHeaders.Contains("Authorization"))
                Client.DefaultRequestHeaders.Remove("Authorization");

            Client.DefaultRequestHeaders.Add("Authorization", auth);

            Client.DefaultRequestHeaders.Accept.Clear();

            //define x-ms-version header
            Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
            if (Client.DefaultRequestHeaders.Contains("x-ms-version"))
                Client.DefaultRequestHeaders.Remove("x-ms-version");

            Client.DefaultRequestHeaders.Add("x-ms-version", apiversion);

            //define the x-ms-date header
            if (Client.DefaultRequestHeaders.Contains("x-ms-date"))
                Client.DefaultRequestHeaders.Remove("x-ms-date");
            Client.DefaultRequestHeaders.Add("x-ms-date", RequestDateString);

            try
            {
                var stringContent = new StringContent(queue_message, Encoding.UTF8, "text/plain");
                var response = Client.PostAsync(uri, stringContent);
                var resu = response.Result;
               
            }
            catch (Exception ex)
            {

            }

            Console.WriteLine("**completed**");
            Console.ReadLine();
        }

        private static String SignThis(String StringToSign, string Key, string Account)
        {
            String signature = string.Empty;
            byte[] unicodeKey = Convert.FromBase64String(Key);
            using (HMACSHA256 hmacSha256 = new HMACSHA256(unicodeKey))
            {
                Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(StringToSign);
                signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
            }

            String authorizationHeader = String.Format(
                  CultureInfo.InvariantCulture,
                  "{0} {1}:{2}",
                  "SharedKey",
                  Account,
                  signature);

            return authorizationHeader;
        }

    }
}

如果您不想生成shared key,因为不容易,您可以使用sas token在REST API中进行身份验证。

这篇关于通过REST API c#使用共享密钥身份验证的Azure存储队列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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