无法使用 Azure 的 REST 创建 Blob 容器 API
Cannot create Blob Container with Azure's REST API
我正在尝试使用 C# 和 REST API(在 Xamarin.Android 中)创建 Blob 容器。我可以将 blob 上传到现有容器,但我似乎无法通过 REST 创建容器。错误是 (403) 服务器无法验证请求。确保 Authorization header 的值正确形成,包括签名。 创建 Authorization Header 在上传 blob 时有效,所以它必须符合我构建的方式容器的字符串要签名,但对于我来说,我找不到问题所在。这是代码:
private async Task<bool> CreateContainer(string containerName)
{
String requestMethod = "PUT";
String msVersion = "2009-09-19";
string dt = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
String canonicalizedHeaders = String.Format("x-ms-date:{0}\nx-ms-version:{1}", dt, msVersion);
String canonicalizedResource = String.Format("/{0}/{1}\nrestype:container", AzureStorageConstants.Account, containerName);
String stringToSign = String.Format("{0}\n\n\n\n\n\n\n\n\n\n\n\n{1}\n{2}", requestMethod, canonicalizedHeaders, canonicalizedResource);
string auth = SignThis(stringToSign);
string urlPath = string.Format("https://{0}.blob.core.windows.net/{1}?restype=container", AzureStorageConstants.Account, containerName);
Uri uri = new Uri(urlPath);
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("x-ms-date", dt);
client.DefaultRequestHeaders.Add("x-ms-version", "2009-09-19");
client.DefaultRequestHeaders.Add("Authorization", auth);
HttpContent empty = null;
HttpResponseMessage response = await client.PutAsync(uri, empty);
return response.IsSuccessStatusCode;
}
private static String SignThis(String StringToSign)
{
String signature = string.Empty;
byte[] unicodeKey = Convert.FromBase64String(AzureStorageConstants.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",
AzureStorageConstants.Account,
signature);
return authorizationHeader;
}
您的请求失败的原因是您没有在 stringToSign
中包含内容长度,即使它包含在请求中(HttpClient 包含它并将其值设置为 0
).这导致签名不匹配。要解决此问题,请在 stringToSign
:
中包含内容长度
String stringToSign = String.Format("{0}\n\n\n0\n\n\n\n\n\n\n\n\n{1}\n{2}", requestMethod, canonicalizedHeaders, canonicalizedResource);
我正在尝试使用 C# 和 REST API(在 Xamarin.Android 中)创建 Blob 容器。我可以将 blob 上传到现有容器,但我似乎无法通过 REST 创建容器。错误是 (403) 服务器无法验证请求。确保 Authorization header 的值正确形成,包括签名。 创建 Authorization Header 在上传 blob 时有效,所以它必须符合我构建的方式容器的字符串要签名,但对于我来说,我找不到问题所在。这是代码:
private async Task<bool> CreateContainer(string containerName)
{
String requestMethod = "PUT";
String msVersion = "2009-09-19";
string dt = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
String canonicalizedHeaders = String.Format("x-ms-date:{0}\nx-ms-version:{1}", dt, msVersion);
String canonicalizedResource = String.Format("/{0}/{1}\nrestype:container", AzureStorageConstants.Account, containerName);
String stringToSign = String.Format("{0}\n\n\n\n\n\n\n\n\n\n\n\n{1}\n{2}", requestMethod, canonicalizedHeaders, canonicalizedResource);
string auth = SignThis(stringToSign);
string urlPath = string.Format("https://{0}.blob.core.windows.net/{1}?restype=container", AzureStorageConstants.Account, containerName);
Uri uri = new Uri(urlPath);
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("x-ms-date", dt);
client.DefaultRequestHeaders.Add("x-ms-version", "2009-09-19");
client.DefaultRequestHeaders.Add("Authorization", auth);
HttpContent empty = null;
HttpResponseMessage response = await client.PutAsync(uri, empty);
return response.IsSuccessStatusCode;
}
private static String SignThis(String StringToSign)
{
String signature = string.Empty;
byte[] unicodeKey = Convert.FromBase64String(AzureStorageConstants.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",
AzureStorageConstants.Account,
signature);
return authorizationHeader;
}
您的请求失败的原因是您没有在 stringToSign
中包含内容长度,即使它包含在请求中(HttpClient 包含它并将其值设置为 0
).这导致签名不匹配。要解决此问题,请在 stringToSign
:
String stringToSign = String.Format("{0}\n\n\n0\n\n\n\n\n\n\n\n\n{1}\n{2}", requestMethod, canonicalizedHeaders, canonicalizedResource);