I have in a sample app been able to reproduce this.
Basically here is the code, use a file in a private container, and the code below works. Then simply rename the blob to have a slash in the front, e.g. "/HdrImage.gif" and in both places shown below insert a slash and it fails with the error and it drops
the extra slashes in the front. The signature must actually embed the incorrect string. Tried to Uri.Encode the name, but doesn't work either.
Any idea, or do I have to rename all of my blobs without the leading slash? When I imported them, I unfortunately put an extra slash in the front of the blob name to simply look "right" with several folder deep structure. Not a fan of folders where they
don't start with a slash! But now trying to get SAS access to content on the fly as users request content, I can't use the SAS because it doesn't work with the leading slashes.
Error Message:
Signature did not match. String to sign used was r 2012-08-13T05:55:08Z /mystorage/test/HdrImage.gif
2012-02-12
Sample Code:
protected void APITest2()
{
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings[connectionStringSettingName]);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
DateTime starttime = DateTime.UtcNow.AddMinutes(-1);
DateTime endtime = DateTime.UtcNow + TimeSpan.FromMinutes(5);
string sig = MakeBlobReadSignature(endtime, "mystorage", "test", "HdrImage.gif");
var uri = new UriBuilder();
uri.Scheme = "http"; // or https works too
uri.Host = string.Format("{0}.{1}", "mystorage", "blob.core.windows.net");
uri.Path = string.Format("test/{0}", "HdrImage.gif");
uri.Query = string.Format("se={1}&sr=b&sp=r&sig={2}",
Uri.EscapeDataString(starttime.ToString("yyyy-MM-ddTHH:mm:ssZ")), //not needed, excluded from string
Uri.EscapeDataString(endtime.ToString("yyyy-MM-ddTHH:mm:ssZ")),
Uri.EscapeDataString(sig));
Response.Write(String.Format("SAS Link: <a href=\"{0}\" target=\"_blank\">{0}</a><br />", uri.ToString()));
}
private string MakeBlobReadSignature(DateTime endtime, string account, string container, string blobname)
{
string stringtosign =
string.Format("r\n\n{1:yyyy-MM-ddTHH:mm:ssZ}\n/{2}/{3}/{4}\n\n2012-02-12",
null, endtime, account, container, blobname); //also excluded the startime here, the null
return storageAccount.Credentials.ComputeHmac(stringtosign);
}
Thank you!