简体   繁体   English

无法使用Azure的REST API创建Blob容器

[英]Cannot create Blob Container with Azure's REST API

I'm trying to create a Blob Container using C# and the REST API (in Xamarin.Android). 我正在尝试使用C#和REST API(在Xamarin.Android中)创建一个Blob容器。 I'm able to upload a blob to an existing container, but I can't seem to create a container via REST. 我能够将blob上传到现有容器,但我似乎无法通过REST创建容器。 The error is (403) Server failed to authenticate the request. 错误是(403)服务器无法验证请求。 Make sure the value of Authorization header is formed correctly including the signature. 确保正确形成Authorization标头的值,包括签名。 Creating the Authorization Header works when uploading a blob, so it must be something with the way I'm constructing the container's string to be signed, but for the life of me I can't find the problem. 创建授权标题在上传blob时起作用,所以它必须是我正在构建要签名的容器字符串的方式,但对于我的生活,我找不到问题。 Here's the code: 这是代码:

    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;
    }

The reason your request is failing is because you're not including the content length in your stringToSign even though it is included in the request (HttpClient is including it and setting its value to 0 ). 您的请求失败的原因是因为您没有在stringToSign包含内容长度,即使它包含在请求中(HttpClient包含它并将其值设置为0 )。 This is causing signature to mismatch. 这导致签名不匹配。 To fix this, include content length in your stringToSign : 要解决此问题,请在stringToSign包含内容长度:

String stringToSign = String.Format("{0}\n\n\n0\n\n\n\n\n\n\n\n\n{1}\n{2}", requestMethod, canonicalizedHeaders, canonicalizedResource);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM