C# 无法使用Azure';创建Blob容器;s REST API

C# 无法使用Azure';创建Blob容器;s REST API,c#,rest,azure,xamarin,azure-storage-blobs,C#,Rest,Azure,Xamarin,Azure Storage Blobs,我正在尝试使用C#和restapi(在Xamarin.Android中)创建一个Blob容器。我可以将blob上传到现有的容器中,但似乎无法通过REST创建容器。错误是(403)服务器无法验证请求。确保包括签名在内的授权标头的值格式正确。上传blob时,创建授权标头是有效的,因此这一定与我构造要签名的容器字符串的方式有关,但就我的一生而言,我找不到问题所在。代码如下: private async Task<bool> CreateContainer(string contai

我正在尝试使用C#和restapi(在Xamarin.Android中)创建一个Blob容器。我可以将blob上传到现有的容器中,但似乎无法通过REST创建容器。错误是(403)服务器无法验证请求。确保包括签名在内的授权标头的值格式正确。上传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;
    }
专用异步任务CreateContainer(字符串containerName)
{          
String requestMethod=“PUT”;
字符串msVersion=“2009-09-19”;
字符串dt=DateTime.UtcNow.ToString(“R”,CultureInfo.InvariantCulture);
String canonicalizedHeaders=String.Format(“x-ms-date:{0}\nx-ms版本:{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);
字符串urlPath=string.Format(“https://{0}.blob.core.windows.net/{1}?restype=container”,AzureStorageConstants.Account,containerName);
Uri=新的Uri(urlPath);
HttpClient=新的HttpClient();
client.DefaultRequestHeaders.Add(“x-ms-date”,dt);
client.DefaultRequestHeaders.Add(“x-ms-version”、“2009-09-19”);
client.DefaultRequestHeaders.Add(“授权”,auth);
HttpContent empty=null;
HttpResponseMessage response=wait client.PutAsync(uri,空);
返回response.IsSuccessStatusCode;
}
私有静态字符串SignThis(字符串StringToSign)
{
字符串签名=String.Empty;
字节[]unicodeKey=Convert.FromBase64String(AzureStorageConstants.Key);
使用(HMACSHA256 HMACSHA256=新的HMACSHA256(Unicode密钥))
{
Byte[]dataToHmac=System.Text.Encoding.UTF8.GetBytes(StringToSign);
signature=Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
}
String authorizationHeader=String.Format(
CultureInfo.InvariantCulture,
"{0} {1}:{2}",
“共享密钥”,
AzureStorageConstants.Account,
签名);
返回授权头;
}

请求失败的原因是,即使请求中包含内容长度,您也没有在
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);