Azure Blob 403 禁止使用 SAS 创建和使用 BlobContainer
Azure Blob 403 Forbidden using SAS to create and use BlobContainer
我正在使用从这篇 MSDN 文章中复制和修改的代码:
MSDN article about Azure SAS usage
我正在使用 Azure 存储模拟器并且可以生成 SAS。这是一个例子:
http://127.0.0.1:10000/devstoreaccount1/7373df60-ad5f-462e-a55d-15c21c2de0e1?sv=2015-04-05&sr=c&si=ac&sig=bQAsuNUsj6MycN0aTyurVugHBMOlokwsXJA9xv7VeiU%3D
我可以使用 Edge 浏览器通过附加来列出 blob 容器:
&comp=list&restype=container
所以我的 link 现在看起来像这样:
http://127.0.0.1:10000/devstoreaccount1/7373df60-ad5f-462e-a55d-15c21c2de0e1?sv=2015-04-05&sr=c&si=ac&sig=bQAsuNUsj6MycN0aTyurVugHBMOlokwsXJA9xv7VeiU%3D&comp=list&restype=container
这让我认为 SAS 是正确的并且存储模拟器正在运行。浏览器显示容器和其中所有 blob 的信息。
我可以检查存储模拟器日志并看到这条消息:
4/21/2016 3:56:10 PM [AuthorizationFailure] [ActivityId=a79d230e-6596-4e43-8ef9-58943ee91b58] Unauthorized: Signed access not supported for this request with FailureReason InvalidOperationSAS
这是我用来创建 SAS 的代码:
String policyName = "ac";
var storedPolicy = new SharedAccessBlobPolicy()
{
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(expireHours),
Permissions = SharedAccessBlobPermissions.Read |
SharedAccessBlobPermissions.List |
SharedAccessBlobPermissions.Delete
};
var permissions = container.GetPermissions();
permissions.SharedAccessPolicies.Clear();
permissions.SharedAccessPolicies.Add(policyName, storedPolicy);
container.SetPermissions(permissions);
string sasContainerToken = container.GetSharedAccessSignature(null, policyName);
// Return the URI string for the container, including the SAS token.
return container.Uri + sasContainerToken;
下面是我使用 SAS 创建 CloudBlobContainer 的代码:
CloudBlobContainer container = new CloudBlobContainer( new Uri(sas) ); // AzureBlob.GetBlobContainer(sas); // gets a new container
if ( ! container.Exists() ) // throws exception
{
throw new Exception("Container no longer exists for sas " + sas);
}
container.FetchAttributes();
这里是例外:
Microsoft.WindowsAzure.Storage.StorageException: The remote server returned an error: (403) Forbidden. ---> System.Net.WebException: The remote server returned an error: (403) Forbidden.
at System.Net.HttpWebRequest.GetResponse()
at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext) in c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\ClassLibraryCommon\Core\Executor\Executor.cs:line 677
--- End of inner exception stack trace ---
at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext) in c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\ClassLibraryCommon\Core\Executor\Executor.cs:line 604
at Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer.Exists(Boolean primaryOnly, BlobRequestOptions requestOptions, OperationContext operationContext) in c:
\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\ClassLibraryCommon\Blob\CloudBlobContainer.cs:line 1406
at Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer.Exists(BlobRequestOptions requestOptions, OperationContext operationContext) in c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\ClassLibraryCommon\Blob\CloudBlobContainer.cs:line 1393
这里是link一篇好像是远房亲戚的文章
SO question about SAS
我不确定你 运行 到底是什么,但这是我根据 https://azure.microsoft.com/en-us/documentation/articles/storage-dotnet-shared-access-signature-part-2/
上的信息整理的
也许可以将您的代码与我的代码进行比较,看看有什么不同
public string CreateSharedAccessSignature(string blobUri, int timeout, TimeUnitType timeUnit)
{
try
{
var uri = new Uri(blobUri);
var cloudBlob = _context.CloudBlobClient.GetBlobReferenceFromServer(uri);
if (!cloudBlob.Exists())
{
throw new StorageException("Blob does not exist");
}
var sasConstraints = new SharedAccessBlobPolicy
{
SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-5),
Permissions = SharedAccessBlobPermissions.Read
};
//The shared access signature will be valid immediately.
switch(timeUnit)
{
case TimeUnitType.Days:
sasConstraints.SharedAccessExpiryTime = DateTime.UtcNow.AddDays(timeout);
break;
case TimeUnitType.Hours:
sasConstraints.SharedAccessExpiryTime = DateTime.UtcNow.AddHours(timeout);
break;
case TimeUnitType.Minutes:
sasConstraints.SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(timeout);
break;
case TimeUnitType.Seconds:
sasConstraints.SharedAccessExpiryTime = DateTime.UtcNow.AddSeconds(timeout);
break;
}
//Generate the shared access signature on the blob, setting the constraints directly on the signature.
string sasBlobToken = cloudBlob.GetSharedAccessSignature(sasConstraints);
return cloudBlob.Uri + sasBlobToken;
}
catch(Exception ex)
{
//new RaygunClient().Send(ex);
throw;
}
}
您的代码失败的原因是您创建的是 Service Shared Access Signature (Service SAS)
而不是 Account Shared Access Signature (Account SAS)
。为了创建 blob 容器,您需要使用 Account SAS 而不是 Service SAS。
从这个页面:https://msdn.microsoft.com/en-us/library/azure/ee395415.aspx
An account-level SAS, introduced with version 2015-04-05. The account
SAS delegates access to resources in one or more of the storage
services. All of the operations available via a service SAS are also
available via an account SAS. Additionally, with the account SAS, you
can delegate access to operations that apply to a given service, such
as Get/Set Service Properties and Get Service Stats. You can also
delegate access to read, write, and delete operations on blob
containers, tables, queues, and file shares that are not permitted
with a service SAS. See Constructing an Account SAS for more
information about account SAS.
下面是创建帐户 SAS 并使用它创建 blob 容器的示例代码:
var storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
var blobClient = storageAccount.CreateCloudBlobClient();
var blobSharedAccessPolicy = new SharedAccessAccountPolicy()
{
Services = SharedAccessAccountServices.Blob,
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(1),
Permissions = SharedAccessAccountPermissions.Write,
ResourceTypes = SharedAccessAccountResourceTypes.Container
};
var sas = storageAccount.GetSharedAccessSignature(blobSharedAccessPolicy);
var containerName = "created-using-account-sas";
var containerUri = string.Format("{0}{1}", storageAccount.BlobEndpoint, containerName);
var blobContainer = new CloudBlobContainer(new Uri(containerUri), new StorageCredentials(sas));
blobContainer.Create();
Console.WriteLine("Container created....");
我正在使用从这篇 MSDN 文章中复制和修改的代码:
MSDN article about Azure SAS usage
我正在使用 Azure 存储模拟器并且可以生成 SAS。这是一个例子:
http://127.0.0.1:10000/devstoreaccount1/7373df60-ad5f-462e-a55d-15c21c2de0e1?sv=2015-04-05&sr=c&si=ac&sig=bQAsuNUsj6MycN0aTyurVugHBMOlokwsXJA9xv7VeiU%3D
我可以使用 Edge 浏览器通过附加来列出 blob 容器:
&comp=list&restype=container
所以我的 link 现在看起来像这样:
http://127.0.0.1:10000/devstoreaccount1/7373df60-ad5f-462e-a55d-15c21c2de0e1?sv=2015-04-05&sr=c&si=ac&sig=bQAsuNUsj6MycN0aTyurVugHBMOlokwsXJA9xv7VeiU%3D&comp=list&restype=container
这让我认为 SAS 是正确的并且存储模拟器正在运行。浏览器显示容器和其中所有 blob 的信息。
我可以检查存储模拟器日志并看到这条消息:
4/21/2016 3:56:10 PM [AuthorizationFailure] [ActivityId=a79d230e-6596-4e43-8ef9-58943ee91b58] Unauthorized: Signed access not supported for this request with FailureReason InvalidOperationSAS
这是我用来创建 SAS 的代码:
String policyName = "ac";
var storedPolicy = new SharedAccessBlobPolicy()
{
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(expireHours),
Permissions = SharedAccessBlobPermissions.Read |
SharedAccessBlobPermissions.List |
SharedAccessBlobPermissions.Delete
};
var permissions = container.GetPermissions();
permissions.SharedAccessPolicies.Clear();
permissions.SharedAccessPolicies.Add(policyName, storedPolicy);
container.SetPermissions(permissions);
string sasContainerToken = container.GetSharedAccessSignature(null, policyName);
// Return the URI string for the container, including the SAS token.
return container.Uri + sasContainerToken;
下面是我使用 SAS 创建 CloudBlobContainer 的代码:
CloudBlobContainer container = new CloudBlobContainer( new Uri(sas) ); // AzureBlob.GetBlobContainer(sas); // gets a new container
if ( ! container.Exists() ) // throws exception
{
throw new Exception("Container no longer exists for sas " + sas);
}
container.FetchAttributes();
这里是例外:
Microsoft.WindowsAzure.Storage.StorageException: The remote server returned an error: (403) Forbidden. ---> System.Net.WebException: The remote server returned an error: (403) Forbidden.
at System.Net.HttpWebRequest.GetResponse()
at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext) in c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\ClassLibraryCommon\Core\Executor\Executor.cs:line 677
--- End of inner exception stack trace ---
at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext) in c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\ClassLibraryCommon\Core\Executor\Executor.cs:line 604
at Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer.Exists(Boolean primaryOnly, BlobRequestOptions requestOptions, OperationContext operationContext) in c:
\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\ClassLibraryCommon\Blob\CloudBlobContainer.cs:line 1406
at Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer.Exists(BlobRequestOptions requestOptions, OperationContext operationContext) in c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\ClassLibraryCommon\Blob\CloudBlobContainer.cs:line 1393
这里是link一篇好像是远房亲戚的文章
SO question about SAS
我不确定你 运行 到底是什么,但这是我根据 https://azure.microsoft.com/en-us/documentation/articles/storage-dotnet-shared-access-signature-part-2/
上的信息整理的也许可以将您的代码与我的代码进行比较,看看有什么不同
public string CreateSharedAccessSignature(string blobUri, int timeout, TimeUnitType timeUnit)
{
try
{
var uri = new Uri(blobUri);
var cloudBlob = _context.CloudBlobClient.GetBlobReferenceFromServer(uri);
if (!cloudBlob.Exists())
{
throw new StorageException("Blob does not exist");
}
var sasConstraints = new SharedAccessBlobPolicy
{
SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-5),
Permissions = SharedAccessBlobPermissions.Read
};
//The shared access signature will be valid immediately.
switch(timeUnit)
{
case TimeUnitType.Days:
sasConstraints.SharedAccessExpiryTime = DateTime.UtcNow.AddDays(timeout);
break;
case TimeUnitType.Hours:
sasConstraints.SharedAccessExpiryTime = DateTime.UtcNow.AddHours(timeout);
break;
case TimeUnitType.Minutes:
sasConstraints.SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(timeout);
break;
case TimeUnitType.Seconds:
sasConstraints.SharedAccessExpiryTime = DateTime.UtcNow.AddSeconds(timeout);
break;
}
//Generate the shared access signature on the blob, setting the constraints directly on the signature.
string sasBlobToken = cloudBlob.GetSharedAccessSignature(sasConstraints);
return cloudBlob.Uri + sasBlobToken;
}
catch(Exception ex)
{
//new RaygunClient().Send(ex);
throw;
}
}
您的代码失败的原因是您创建的是 Service Shared Access Signature (Service SAS)
而不是 Account Shared Access Signature (Account SAS)
。为了创建 blob 容器,您需要使用 Account SAS 而不是 Service SAS。
从这个页面:https://msdn.microsoft.com/en-us/library/azure/ee395415.aspx
An account-level SAS, introduced with version 2015-04-05. The account SAS delegates access to resources in one or more of the storage services. All of the operations available via a service SAS are also available via an account SAS. Additionally, with the account SAS, you can delegate access to operations that apply to a given service, such as Get/Set Service Properties and Get Service Stats. You can also delegate access to read, write, and delete operations on blob containers, tables, queues, and file shares that are not permitted with a service SAS. See Constructing an Account SAS for more information about account SAS.
下面是创建帐户 SAS 并使用它创建 blob 容器的示例代码:
var storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
var blobClient = storageAccount.CreateCloudBlobClient();
var blobSharedAccessPolicy = new SharedAccessAccountPolicy()
{
Services = SharedAccessAccountServices.Blob,
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(1),
Permissions = SharedAccessAccountPermissions.Write,
ResourceTypes = SharedAccessAccountResourceTypes.Container
};
var sas = storageAccount.GetSharedAccessSignature(blobSharedAccessPolicy);
var containerName = "created-using-account-sas";
var containerUri = string.Format("{0}{1}", storageAccount.BlobEndpoint, containerName);
var blobContainer = new CloudBlobContainer(new Uri(containerUri), new StorageCredentials(sas));
blobContainer.Create();
Console.WriteLine("Container created....");