Azure 存储 SAS 身份验证失败

Azure Storage SAS AuthenticationFailed

我有一个私有的 azure 存储容器,正在试用 azure storage SAS,以便我可以上传和下载文件。 我能够生成签名,但它总是向我抛出身份验证失败错误

AuthenticationFailed Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. RequestId:a9dce486-0001-0021-23f7-d8f6dc000000 Time:2017-05-30T03:45:56.6617677Z Signature did not match. String to sign used was r 2017-05-30T03:40:48Z 2017-05-30T03:55:48Z /blob/{myaccount}/{mycontainer}/11e1575f-d3ad-40cc-b1ce-32e24dc20324.jpg

2016-05-31

这是我生成签名供我使用的代码,以及 returns 用于访问文件的完整 URI。

var accountAndKey = new StorageCredentials("******", "*********************");
var storageAccount = new CloudStorageAccount(accountAndKey, true);

var sasConstraints = new SharedAccessBlobPolicy();
sasConstraints.SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-5);
sasConstraints.SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(10);
sasConstraints.Permissions = SharedAccessBlobPermissions.Read;


CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("*****");
CloudBlockBlob blockBlob = container.GetBlockBlobReference("11e1575f-d3ad-40cc-b1ce-32e24dc20324.jpg");

var sasBlobToken = blockBlob.GetSharedAccessSignature(sasConstraints);

var sas = blockBlob.Uri + sasBlobToken;

return sas;

这是它生成的签名

?sv=2016-05-31&sr=b&sig=9fUwDWfdtUifv9iZXJKgILEM7Yx1uP3Ku0vrspjWyz8%3D&st=2017-05-30T03%3A40%3A43Z&se=2017-05-30T03%3A55%3A43Z&sp=r

我使用 Azure 门户生成签名,它工作正常。我附加它并能够像往常一样下载文件。 这是它生成的签名

?sv=2016-05-31&ss=b&srt=sco&sp=r&se=2017-05-30T03:57:25Z&st=2017-05-30T03:52:25Z&spr=https&sig=JOnhkge0QWNdv8sXJjb5GazTo9c34KH1IvZBvcNgjHo%3D

我高度怀疑时间戳有问题。因为我可以看到我从代码生成的时间戳与从门户网站生成的时间戳有所不同。

非常感谢任何想法。谢谢。

编辑 我更新了代码以添加一天直到到期并删除了开始时间,这是现在的签名

?sv=2016-05-31&sr=b&sig=73m3%2Bj%2BUsFk537vd8a7F%2BdpdON1Pg2RZ1IRynMH4zGA%3D&se=2017-05-31T06%3A12%3A07Z&sp=r

但它仍然不允许我下载文件。相同的错误消息。

Signature did not match. String to sign used was r 2017-05-31T06:12:07Z /blob/{MyAcc}/{My Container}/11e1575f-d3ad-40cc-b1ce-32e24dc20324.jpg 2016-05-31

我也无法使用代码重现该问题。这是一种无需使用 GetSharedAccessSignature 方法即可生成 SAS 的方法。请尝试一下,看看它是否可以在你身边工作。

private static string GetSharedAccessSignature(
       string accountName,
       string accountkey,
       string blobContainer,
       string blobName,
       DateTimeOffset sharedAccessStartTime,
       DateTimeOffset sharedAccessExpiryTime)
{
    var canonicalNameFormat = $"/blob/{accountName}/{blobContainer}/{blobName}";
    var st = sharedAccessStartTime.UtcDateTime.ToString("yyyy-MM-ddTHH:mm:ssZ");
    var se = sharedAccessExpiryTime.UtcDateTime.ToString("yyyy-MM-ddTHH:mm:ssZ");
    var sasVersion = "2016-05-31";

    string stringToSign = string.Format("{0}\n{1}\n{2}\n{3}\n{4}\n{5}\n{6}\n{7}\n{8}\n{9}\n{10}\n{11}\n{12}", new object[]
    {
        "r",
        st,
        se,
        canonicalNameFormat,
        string.Empty,
        string.Empty,
        string.Empty,
        sasVersion,
        string.Empty,
        string.Empty,
        string.Empty,
        string.Empty,
        string.Empty
    });

    var sas = GetHash(stringToSign, accountkey);

    var credentials =
        $"?sv={sasVersion}&sr=b&sig={UrlEncoder.Default.Encode(sas)}&st={UrlEncoder.Default.Encode(st)}&se={UrlEncoder.Default.Encode(se)}&sp=r";

    string blobUri = $"https://{accountName}.blob.core.windows.net/{blobContainer}/{blobName}";
    return blobUri + credentials;
}

private static string GetHash(string stringToSign, string key)
{
    byte[] keyValue = Convert.FromBase64String(key);

    using (HMACSHA256 hmac = new HMACSHA256(keyValue))
    {
        return Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
    }
}