1

I am using this code to upload some text directly to azure blob using rest api. I am getting an webexception 403 forbidden. Can someone plaese tell me where am i going wrong in my code

    private String CreateAuthorizationHeader(String canonicalizedString, CloudBlob blob)
    {
        String signature = string.Empty;


        using (HMACSHA256 hmacSha256 = new HMACSHA256())
        {
            Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(canonicalizedString);
            signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
        }


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

        return authorizationHeader;
   }

    private void PutBlob(String containerName, String blobName , CloudBlob blob)
    {
        String requestMethod = "PUT";

        String urlPath = String.Format("{0}",  blobName);

        String storageServiceVersion = "2009-10-01";

        String dateInRfc1123Format = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);

       // if (uploadPST.HasFile)
      //  {
            string content = "Sample file";
            // Stream content = uploadPST.FileBytes; 
            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-ms-date:{0}\nx-ms-meta-m1:{1}\nx-ms-meta-m1:{2}",
                   dateInRfc1123Format,
                  "v1",
                  "v2");

            String canonicalizedResource = String.Format("/{0}/{1}", myaccount, urlPath);

           String stringToSign = String.Format(
                  "{0}\n\n{1}\n\n{2}\n{3}",
                  requestMethod,
                  "text/plain; charset=UTF-8",
                  canonicalizedHeaders,
                  canonicalizedResource);



            String authorizationHeader = CreateAuthorizationHeader(stringToSign, blob);

            Uri uri = new Uri(CloudStorageAccount.FromConfigurationSetting("DataConnectionString").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;

            using (Stream requestStream = request.GetRequestStream())
            {
                requestStream.Write(blobContent ,0 ,blobLength);
            }

            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                String ETag = response.Headers["ETag"];
            }
      //  }
    }
user565080
  • 11
  • 2
  • FYI for others, this is being discussed on the Windows Azure forum on MSDN: http://social.msdn.microsoft.com/Forums/en-US/windowsazuredata/thread/0526ccc4-63e3-404f-a355-28179b6e88cb – user94559 Jan 06 '11 at 09:37

1 Answers1

0

First, you construct an HMACSHA256 object using the default constructor -- this causes a random key to be generated and used for signing. What you want is the overload which accepts a string - and pass the azure account key.

Still, signing the request 'manually' can be tricky, as there are a lot of things to do and it's easy to mess up or forget something. Instead, I recommend you use the SignRequest method of StorageCredentialsAccountAndKey class (msdn doc) For instance;

// ...there exists a request object, and strings for the account name and key

var creds = new StorageCredentialsAccountAndKey(accountName, accountKey);
creds.SignRequest(request);

This will do everything needed to sign the request properly, including creating a canonicalized headers string, creating a date with the correct format, etc.

Digitalex
  • 1,494
  • 9
  • 11