【问题标题】:Azure Blob 403 Forbidden using SAS to create and use BlobContainerAzure Blob 403 Forbidden 使用 SAS 创建和使用 BlobContainer
【发布时间】:2016-08-15 08:30:44
【问题描述】:

我正在使用从这篇 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

所以我的链接现在看起来像这样:

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

这里是一篇貌似是远亲的文章的链接。

SO question about SAS

【问题讨论】:

    标签: c# azure azure-blob-storage


    【解决方案1】:

    我不确定您到底遇到了什么,但这是我根据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;
            }
        }
    

    【讨论】:

      【解决方案2】:

      您的代码失败的原因是您创建的是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

      帐户级 SAS,在 2015-04-05 版本中引入。账户 SAS 委托访问一个或多个存储中的资源 服务。通过服务 SAS 可用的所有操作也是 可通过账户 SAS 获得。此外,使用账户 SAS,您 可以委托访问适用于给定服务的操作,例如 作为获取/设置服务属性和获取服务统计信息。 你也可以 委托对 blob 的读取、写入和删除操作的访问权限 不允许的容器、表、队列和文件共享 使用服务 SAS。有关更多信息,请参阅构建帐户 SAS 有关帐户 SAS 的信息。

      以下是创建 Account 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....");
      

      【讨论】:

      • 嗨,高拉夫!感谢您对此的帮助。在更改此行 var containerUri = string.Format("{0}/{1}", storageAccount.BlobEndpoint, containerName); 之前出现错误,我更改为添加权限以允许读取、写入、创建、列出和删除。但是当我尝试将 blob 上传到容器时,我得到 403 Forbidden。我现有的代码在创建容器和上传 blob 方面效果很好。我的问题是我可以在创建容器并上传 blob 后应用权限并获取 SAS 吗?如果没有,在尝试上传 blob 时如何避免 403 错误?
      • 好的,我更进一步了。我添加了 SharedAccessResourceTypes.Blob 并能够将 blob 上传到新容器。 sas 看起来像这样 http://127.0.0.1:10000/devstoreaccount1/45a56968-459a-4a65-995d-06e233e1d015?sv=2015-04-05&sig=zXJC6hIjD77c3b1oKZWlW9YtuHMF78zR7NxVc%2FcYMQs%3D&se=2016-04-22T17%3A20%3A40Z&srt=co&ss=b&sp=rcwdl 当我尝试在另一个程序中使用这个 sas 时,我得到 System.ArgumentException: Missing required parameters for valid Shared Access Signature 关于这个有什么想法吗?
      • When I attempt to use this sas in another program --> 你能详细描述一下吗?将其作为一个新问题发布可能不是一个坏主意。
      • 我有一个创建容器和上传 blob 的服务。该服务会将 SAS 返回给用户的客户端程序。然后客户端程序尝试使用 SAS 列出容器中的所有 blob 并下载它们。
      • 更多进展。我已将客户端代码更改为credentials = new StorageCredentials(sastoken); container = new CloudBlobContainer(new Uri(uri), credentials);,现在得到一个容器。但是当我检查 container.Exists() 时,找不到 404。这很奇怪。如果我使用 uri 和 sas 令牌,我可以看到容器和 blob:[link]127.0.0.1:10000/devstoreaccount1/…
      猜你喜欢
      • 1970-01-01
      • 2019-07-09
      • 2022-01-17
      • 2016-10-07
      • 2021-09-02
      • 2020-03-18
      • 1970-01-01
      • 2014-07-13
      • 1970-01-01
      相关资源
      最近更新 更多