[英]Azure Blob Storage 403 Authentication Failed
我使用Azure Blob存儲來存儲我的應用程序文件。 我已經毫不費力地為公共容器做了這件事,但我發現在將它們設為私有時遇到了一些麻煩。
要訪問我的私有包含中的文件,我使用以下方法來檢索最終的URL:
public static string GetBlobSasUri(string containerLocation, string blobName, string policyName = null)
{
string sasBlobToken;
// Get a reference to a blob within the container.
// Note that the blob may not exist yet, but a SAS can still be created for it.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.
ConnectionStrings["AzureConnection"].ConnectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(containerLocation);
CloudBlockBlob blob = container.GetBlockBlobReference(blobName);
if (policyName == null)
{
// Create a new access policy and define its constraints.
// Note that the SharedAccessBlobPolicy class is used both to define the parameters of an ad-hoc SAS, and
// to construct a shared access policy that is saved to the container's shared access policies.
SharedAccessBlobPolicy adHocSAS = new SharedAccessBlobPolicy()
{
// When the start time for the SAS is omitted, the start time is assumed to be the time when the storage service receives the request.
// Omitting the start time for a SAS that is effective immediately helps to avoid clock skew.
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24),
Permissions = SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Create
};
// Generate the shared access signature on the blob, setting the constraints directly on the signature.
sasBlobToken = blob.GetSharedAccessSignature(adHocSAS);
Console.WriteLine("SAS for blob (ad hoc): {0}", sasBlobToken);
Console.WriteLine();
}
else
{
// Generate the shared access signature on the blob. In this case, all of the constraints for the
// shared access signature are specified on the container's stored access policy.
sasBlobToken = blob.GetSharedAccessSignature(null, policyName);
Console.WriteLine("SAS for blob (stored access policy): {0}", sasBlobToken);
Console.WriteLine();
}
// Return the URI string for the container, including the SAS token.
return blob.Uri + sasBlobToken;
}
但是當我嘗試通過瀏覽器中的最終URI時,我總是會收到此錯誤:
<Error>
<Code>AuthenticationFailed</Code>
<Message>
Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. RequestId:96d18e26-0001-008e-7eb3-c88fcd000000 Time:2017-05-09T11:01:24.9128128Z
</Message>
<AuthenticationErrorDetail>
Signature did not match. String to sign used was rcw 2017-05-10T11:01:06Z /blob/mystorage/profiles/317ce29e-86c9-46d8-8579-8cbdaf385971pic.png 2016-05-31
</AuthenticationErrorDetail>
</Error>
任何想法為什么?
更新:連接字符串:
<add name="AzureConnection" connectionString="DefaultEndpointsProtocol=https;AccountName=mystorage;AccountKey=5Z+lqPDdRDdlVwSW6kA3iOIb8jUjJkib6A/gAQ8UeqcgPcsW1Do0NbypYsUguTOpb41cO0S0k2wdBEeqvtxaXQ==;EndpointSuffix=core.windows.net" />
Azure Storage Explorer生成的URL:
https://mystorage.blob.core.windows.net/profiles/169ae1c0-3307-401f-b45c-a50fa86cb1c6pic.png?sv=2016-05-31&ss=b&srt=sco&sp=r&se=2017-05-11T19:19:43Z&st=2017-05-11T09:19:43Z&spr=https&sig=ZpdhWPHZaUwECoorBwWidaresP50jannOx6ECUdd2Vw%3D
sv=2016-05-31
ss=b
srt=sco
sp=r
se=2017-05-11T19:19:43Z
st=2017-05-11T09:19:43Z
spr=https
sig=ZpdhWPHZaUwECoorBwWidaresP50jannOx6ECUdd2Vw%3D
代碼生成的網址:
https://mystorage.blob.core.windows.net/profiles/169ae1c0-3307-401f-b45c-a50fa86cb1c6pic.png?sv=2016-05-31&sr=c&sig=JQgK68ycbhyq1xQ%2BQb6UDrUCcy3jwA8FEZVYununZVE%3D&st=2017-05-11T08%3A19%3A47Z&se=2017-05-11T12%3A19%3A47Z&sp=r
sv=2016-05-31
sr=c
sig=JQgK68ycbhyq1xQ%2BQb6UDrUCcy3jwA8FEZVYununZVE%3D
st=2017-05-11T08%3A19%3A47Z
se=2017-05-11T12%3A19%3A47Z
sp=r
最新更新29/05/2017:
我決定改變我的方法並試試這個:
public static string GetBlobSasUri(string containerLocation, string blobName, string policyName = null)
{
string sasBlobToken;
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.
ConnectionStrings["AzureStoreConnection"].ConnectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(containerLocation);
container.CreateIfNotExists();
if (policyName == null)
{
SharedAccessBlobPolicy adHocSAS = new SharedAccessBlobPolicy()
{
SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(120),
SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-120),
Permissions = SharedAccessBlobPermissions.Read
};
CloudBlockBlob blob = container.GetBlockBlobReference(blobName);
sasBlobToken = blob.GetSharedAccessSignature(adHocSAS);
Console.WriteLine("SAS for blob (ad hoc): {0}", sasBlobToken);
Console.WriteLine();
return blob.Uri + HttpUtility.UrlEncode(sasBlobToken);
}
return null;
}
錯誤更改,現在我收到以下錯誤: 指定的資源不存在。
錯誤更改,現在我收到以下錯誤:指定的資源不存在。
如果您對令牌進行了編碼,則最終的URL如下所示。 它不是一個格式良好的帶有SAS的blob URL。
https://accountname.blob.core.windows.net/containername/blobname.jpg%3fsv%3d2016-05-31%26sr%3db%26sig%3dNGZzNbKvnR%252FRCnz1Dsk%252FJrSn8lVdqszyCF8MuLsdo0I%253D%26st%3d2017-05-31T05%253A32%253A00Z%26se%3d2017-05-31T09%253A32%253A00Z%26sp%3dr
這是一種可以在不使用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)));
}
}
你需要返回'blob.Uri.AbsoluteUri + sasBlobToken'。
此外,建議將SharedAccessStartTime設置為(Now - 5m)以克服計算機之間的時鍾差異。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.