Uploading through REST API to blob storage throws (403) Forbidden Error.

Răspuns Uploading through REST API to blob storage throws (403) Forbidden Error.

  • 29 aprilie 2012 17:46
     
      Are cod

    Can someone help. Am facing same problem.. but using simple code to do things. Can someone help please.

    Note - Am able to upload the same data using StorageClient dll.

    But with Http, am facing issues. On desktop it says (403) Forbidden Error. I have used Fiddler to fig what my StorageClient is sending & replicated that in HttpWebRequest.

    Thanks.

    public bool StartGPSDataUpload(Guid raceId)
            {
                bool bResult = false;
                try
                {
                    string URL = "";
                    URL = "http://xxxx.blob.core.windows.net/videos/"+ Uri.EscapeDataString("6a3c2acd-8a2f-41ee-9203-137d7ba7ecd5-GPS-test.txt") +"?timeout=90";
                    WebReq = (HttpWebRequest)HttpWebRequest.Create(URL);
                    WebReq.Method = "PUT";
                    WebReq.KeepAlive = false;
                    WebReq.Headers["x-ms-version"] = "2011-08-18";
                    WebReq.UserAgent = "myapp";
                    WebReq.Headers["x-ms-blob-type"] = "BlockBlob";
                    WebReq.Headers["x-ms-date"] = DateTime.UtcNow.ToString("R");
                    WebReq.Headers["Authorization"] = "SharedKey xxxx:ioOqYh7CnftgX8c1DxX5OiRWL1v9TfIJMmTl8m4ogrY=";
                    gpsdataInByte = ReadGPSFile(raceId);
                    WebReq.ContentLength = gpsdataInByte.Length;
                    
                    using (HttpWebResponse response = (HttpWebResponse)WebReq.GetResponse())
                    {
                        String ETag = response.Headers["ETag"];
                        System.Windows.Forms.MessageBox.Show(ETag);
                    }
                    
                }
                catch (Exception ex)
                {
                    System.Windows.Forms.MessageBox.Show("error - " + ex.ToString());
                }
    
                return bResult;
            }

Toate mesajele

  • 29 aprilie 2012 18:42
     
     Răspuns
    How are you deriving the auth signature? I don't see any code that computes the canonicalized resource, headers, etc., and signs them. I think perhaps you're assuming a simpler auth scheme than is actually used by WA storage.
  • 30 aprilie 2012 15:32
     
      Are cod

    Hello Steve,

    You are right. I was assuming it to be simpler. I was able to get things working. Thanks for the tip.

    For others who may benefit from my stumbles, here is the sample code.

    This article was helful http://convective.wordpress.com/2010/08/18/examples-of-the-windows-azure-storage-services-rest-api/

    Here is the sample code for others. Usage will be (new AzureStorageHelper()).PutBlob("yourcontainername", "yourblobfilename");

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Security.Cryptography;
    using System.Globalization;
    using System.Net;
    using System.IO;
    
    namespace TestBlobUpload
    {
        class AzureStorageConstants
        {
            public static string Key="xxxx";
            public static string SharedKeyAuthorizationScheme = "SharedKey";
            public static string Account="xxxx";
            public static string BlobEndPoint="http://xxxxx.blob.core.windows.net/";
            
        }
        class AzureStorageHelper
        {
            public String CreateAuthorizationHeader(String canonicalizedString)
             {
                 String signature = string.Empty;
                 //UTF8Encoding utf8Encoding = new UTF8Encoding();
                 //byte[] storageKey = utf8Encoding.GetBytes(AzureStorageConstants.Key);
                 byte[] storageKey = Convert.FromBase64String(AzureStorageConstants.Key);
    
                 using (HMACSHA256 hmacSha256 = new HMACSHA256(storageKey))
                 {
                     Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(canonicalizedString);
                     signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
                 }
     
                String authorizationHeader = String.Format(
                       CultureInfo.InvariantCulture,
                       "{0} {1}:{2}",
                       AzureStorageConstants.SharedKeyAuthorizationScheme,
                       AzureStorageConstants.Account,
                       signature);
     
                return authorizationHeader;
             }
    
            public void PutBlob(String containerName, String blobName)
             {
                 String requestMethod = "PUT";
     
                String urlPath = String.Format("{0}/{1}", containerName, blobName);
    
                String storageServiceVersion = "2011-08-18"; // "2009-09-19";
     
                String dateInRfc1123Format = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
     
                String content = "The Name of This Band is Talking Heads";
                 UTF8Encoding utf8Encoding = new UTF8Encoding();
                 Byte[] blobContent = utf8Encoding.GetBytes(content);
                 Int32 blobLength = blobContent.Length;
     
                const String blobType = "BlockBlob";
     
                
                String canonicalizedHeaders = String.Format(
                       "x-ms-blob-type:{0}\nx-ms-date:{1}\nx-ms-version:{2}",
                       blobType,
                       dateInRfc1123Format,
                       storageServiceVersion);
                /*
                String canonicalizedHeaders = String.Format(
                 "x-mx-blob-content-length:{3}\nx-ms-blob-type:{0}\nx-ms-date:{1}\nx-ms-version:{2}",
                 blobType,
                 dateInRfc1123Format,
                 storageServiceVersion,
                 blobLength.ToString());
                */
                 String canonicalizedResource = String.Format("/{0}/{1}", AzureStorageConstants.Account, urlPath);
                 String stringToSign = String.Format(
                       "{0}\n\n\n{1}\n\n\n\n\n\n\n\n\n{2}\n{3}",
                       requestMethod,
                       blobLength,
                       canonicalizedHeaders,
                       canonicalizedResource);
                 String authorizationHeader = CreateAuthorizationHeader(stringToSign);
     
                Uri uri = new Uri(AzureStorageConstants.BlobEndPoint + urlPath);
                 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
                 request.Method = requestMethod;
                 request.Headers.Add("x-ms-blob-type", blobType);
                 request.Headers.Add("x-ms-date", dateInRfc1123Format);
                 request.Headers.Add("x-ms-version", storageServiceVersion);
                 request.Headers.Add("Authorization", authorizationHeader);
                 request.ContentLength = blobLength;
    
                 try
                 {
                     using (Stream requestStream = request.GetRequestStream())
                     {
                         requestStream.Write(blobContent, 0, blobLength);
                     }
    
                     using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                     {
                         String ETag = response.Headers["ETag"];
                     }
                     System.Windows.Forms.MessageBox.Show("Success");
                 }
                 catch (WebException webEx)
                 {
                     if (webEx != null)
                     {
                         WebResponse resp = webEx.Response;
                         if (resp != null)
                         {
                             using (StreamReader sr = new StreamReader(resp.GetResponseStream(), true))
                             {
                                 string responseText = sr.ReadToEnd();//This is where details about this 403 message can be found
                                 System.Windows.Forms.MessageBox.Show("error - " + responseText);
                             }
                         }
                     }
                 }
             }
    
        }
    }