【问题标题】:Azure REST API - Server failed to authenticateAzure REST API - 服务器无法进行身份验证
【发布时间】:2015-09-03 20:27:12
【问题描述】:

我正在创建能够将一些 blob 上传到 Azure 存储的 Windows Phone 8.1 Store 应用程序。我不能使用 WindowsAzure.Storage lib(很奇怪),所以我正在尝试使用 REST。我想不通,怎么了。

try
{
    string time = DateTime.Now.ToString("R", System.Globalization.CultureInfo.InvariantCulture);
    string tosign = "GET\n" +
                        "\n" +  //Content-Encoding
                        "\n" +  //Content-Language
                        "0\n" +  //Content-Length
                        "\n" +  //Content-MD5
                        "\n" +  //Content-Type
                        "\n" +  //Date
                        "\n" +  //If-modified-since
                        "\n" +  //If-match
                        "\n" +  //If-none-match
                        "\n" +  //If-unmodified-since
                        "\n" +  //Range
                        "x-ms-date:" + time + "\nx-ms-version:2015-02-21\n" +   //CanonicalizedHeaders
                        "/storage_name/\ncomp:list";    //CanonicalizedResource

    string hashKey = "DHpNuYG5MXhamfbKmFPClUlNi38QiM2uqIqz07pgvpv2gmXJRwxaMlcV05pFCYsrelGYKPed9QphyJ/YnUrh5w=="; //Primary access key

    MacAlgorithmProvider macAlgorithmProvider = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha256);
    var messageBuffer = CryptographicBuffer.ConvertStringToBinary(tosign, BinaryStringEncoding.Utf8);
    IBuffer keyBuffer = CryptographicBuffer.ConvertStringToBinary(hashKey, BinaryStringEncoding.Utf8);
    CryptographicKey hmacKey = macAlgorithmProvider.CreateKey(keyBuffer);
    IBuffer signedMessage = CryptographicEngine.Sign(hmacKey, messageBuffer);
    string hashedString = CryptographicBuffer.EncodeToBase64String(signedMessage);

    var client = new HttpClient();
    Uri uri = new Uri("https://storage_name.blob.core.windows.net/?comp=list");
    client.DefaultRequestHeaders.Add("x-ms-date", time);
    client.DefaultRequestHeaders.Add("x-ms-version", "2015-02-21");
    client.DefaultRequestHeaders.Add("Authorization", "SharedKey storage_name:" + hashedString);
    var response = await client.GetAsync(uri);
}
catch(Exception ex)
{
    Debug.WriteLine(ex.ToString());
}

错误:服务器未能验证请求。确保 Authorization 标头的值格式正确,包括签名。

我怎样才能让它发挥作用?

【问题讨论】:

  • 我猜,我的加密方法有错误。

标签: c# azure windows-runtime windows-phone-8.1 sha256


【解决方案1】:

您的密码有误。 :-)

代码示例

以下是“在 UTF-8 编码的签名字符串上调用 HMAC-SHA256 算法并将结果编码为 Base64”的工作代码示例。在以下示例中,hashKey 参数是来自 Azure 的“主访问密钥”,toSign 参数是来自docs 的“签名字符串”。

在 Windows Phone 8.1 上编码签名

在 Windows Phone 8.1 上,我们使用 Windows.Security.Cryptography 命名空间,如下所示:

public string GetEncodedSignature(string toSign, string hashKey)
{
    // UTF-8-encoded signature string
    var utf8 = BinaryStringEncoding.Utf8;
    var msgBuffer = CryptographicBuffer.ConvertStringToBinary(toSign, utf8);

    // primary access key
    // note the use of DecodeFromBase64String
    var keyBuffer = CryptographicBuffer.DecodeFromBase64String(hashKey);

    // make the HMAC-SHA256 algorithm
    var alg = MacAlgorithmNames.HmacSha256;
    var objMacProv = MacAlgorithmProvider.OpenAlgorithm(alg);
    CryptographicHash hash = objMacProv.CreateHash(keyBuffer);

    // call the HMAC-SHA256 algorithm
    hash.Append(msgBuffer);
    IBuffer hashMsg = hash.GetValueAndReset();

    // retrieve the result!
    var result = CryptographicBuffer.EncodeToBase64String(hashMsg);

    return result;
}

在 .NET 中编码签名

我还创建了使用System.Security.Cryptography 命名空间的an example for .NET

public static string GetEncodedSignature(string toSign, string hashKey)
{
    byte[] bytes;
    byte[] unicodeKey = Convert.FromBase64String(hashKey);
    var utf8encodedString = Encoding.UTF8.GetBytes(toSign);
    using (var hmac = new HMACSHA256(unicodeKey))
    {
        bytes = hmac.ComputeHash(utf8encodedString);
    }

    var signature = Convert.ToBase64String(bytes);
    return signature;
}

当给定相同的输入时,两个代码示例都会产生相同的编码签名。您可以在Fiddle that generates the HTTP Request 上更详细地查看其中之一。

另见

MSDN Article Authentication for the Azure Storage Services

【讨论】:

    【解决方案2】:

    可能您已经解决了这个问题,但如果没有解决,或者对于其他任何人,我也遇到了同样的问题,对我来说,解决方法是将 Content-Length 更改为“\n”(而不是“0\ n")。从版本 2015-02-21 及更高版本开始,您无需指定长度。

    try
    {
        string time = DateTime.Now.ToString("R", System.Globalization.CultureInfo.InvariantCulture);
        string tosign = "GET\n" +
                            "\n" +  //Content-Encoding
                            "\n" +  //Content-Language
                            "\n" +  //Content-Length
                            "\n" +  //Content-MD5
                            "\n" +  //Content-Type
                            "\n" +  //Date
                            "\n" +  //If-modified-since
                            "\n" +  //If-match
                            "\n" +  //If-none-match
                            "\n" +  //If-unmodified-since
                            "\n" +  //Range
                            "x-ms-date:" + time + "\nx-ms-version:2015-02-21\n" +   //CanonicalizedHeaders
                            "/storage_name/\ncomp:list";    //CanonicalizedResource
    
        string hashKey = "DHpNuYG5MXhamfbKmFPClUlNi38QiM2uqIqz07pgvpv2gmXJRwxaMlcV05pFCYsrelGYKPed9QphyJ/YnUrh5w=="; //Primary access key
    
    
       string hashedString = GetEncodedSignature(tosign, hashKey); //Shaun's answer method
    
        var client = new HttpClient();
        Uri uri = new Uri("https://storage_name.blob.core.windows.net/?comp=list");
        client.DefaultRequestHeaders.Add("x-ms-date", time);
        client.DefaultRequestHeaders.Add("x-ms-version", "2015-02-21");
        client.DefaultRequestHeaders.Add("Authorization", "SharedKey storage_name:" + hashedString);
        var response = await client.GetAsync(uri);
    }
    catch(Exception ex)
    {
        Debug.WriteLine(ex.ToString());
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-19
      • 1970-01-01
      • 2020-01-15
      • 2016-04-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多