【问题标题】:Azure CloudBlobContainer.CreateIfNotExists returns 403 forbiddenAzure CloudBlobContainer.CreateIfNotExists 返回 403 禁止
【发布时间】:2014-09-03 17:15:29
【问题描述】:

我从 Web API 服务中间接调用 CloudBlobContainer.CreateIfNotExist(请参阅下面的 FindOrCreatePrivateBlobContainer 方法),但它返回以下 403 禁止错误消息:

<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
The remote server returned an error: (403) Forbidden.
</ExceptionMessage>
<ExceptionType>Microsoft.WindowsAzure.Storage.StorageException</ExceptionType>
<StackTrace>
at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext) at Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer.Exists(Boolean primaryOnly, BlobRequestOptions requestOptions, OperationContext operationContext) at Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer.CreateIfNotExists(BlobContainerPublicAccessType accessType, BlobRequestOptions requestOptions, OperationContext operationContext) at Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer.CreateIfNotExists(BlobRequestOptions requestOptions, OperationContext operationContext) at [Obfuscated].DocumentManagement.BlobStorage.BlobHelper.FindOrCreatePrivateBlobContainer(String ContainerName, String AccountConnectionString) in c:\Users\[Obfuscated]\Desktop\[ProjectNameObfuscated]Online\[Obfuscated].DocumentManagement.BlobStorage\BlobHelper.cs:line 25 at [Obfuscated].DocumentManagement.BlobStorage.BlobFileItemHandler.GetStream(Int64 FileItemId) in c:\Users\[Obfuscated]\Desktop\[ProjectNameObfuscated]Online\[Obfuscated].DocumentManagement.BlobStorage\BlobFileItemHandler.cs:line 114 at [Obfuscated].DocumentManagement.Service.Controllers.FileItemController.Get(String ServiceAuthKey, Int64 FileItemId) in c:\Users\[Obfuscated]\Desktop\[ProjectNameObfuscated]Online\[Obfuscated].DocumentManagement.Service\Controllers\FileItemController.cs:line 148 at lambda_method(Closure , Object , Object[] ) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()
</StackTrace>
<InnerException>
<Message>An error has occurred.</Message>
<ExceptionMessage>
The remote server returned an error: (403) Forbidden.
</ExceptionMessage>
<ExceptionType>System.Net.WebException</ExceptionType>
<StackTrace>
at System.Net.HttpWebRequest.GetResponse() at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext)
</StackTrace>
</InnerException>
</Error>

这是产生错误的代码:

     public HttpResponseMessage Get(string ServiceAuthKey, Int64 FileItemId)
        {
            if (!CheckServiceAuthKey(ServiceAuthKey).IsSuccessStatusCode)
                return new HttpResponseMessage(HttpStatusCode.Unauthorized);

            HttpRequest request = HttpContext.Current.Request;

            FileItem fi = null;
            using (DocumentDbContext db = new DocumentDbContext())
            {
                fi = db.FileItems.Find(FileItemId);
            }


            BlobFileItemHandler fih = new BlobFileItemHandler();
            Stream s = fih.GetStream(FileItemId);


            // -------- DOWNLOAD FILE TO CLIENT -------- 

            HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
            response.Content = new StreamContent(s);
            //a text file is actually an octet-stream (pdf, etc)
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
            //we used attachment to force download
            response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
            response.Content.Headers.ContentDisposition.FileName = fi.PublicFileName;


            return response;
        }

 public Stream GetStream(Int64 FileItemId)
        {
            CloudBlobContainer c = BlobHelper.FindOrCreatePrivateBlobContainer("[Obfuscated]-dms", AccountConnectionString);

            using (DocumentDbContext db = new DocumentDbContext())
            {
                FileItem fi = db.FileItems.Find(FileItemId);

                CloudBlockBlob blob = c.GetDirectoryReference(fi.FilePathOnServer).GetBlockBlobReference(fi.PrivateFileName);
                bool blobExists = blob.Exists();

                if (!blobExists)
                    throw new System.IO.FileNotFoundException();

                Stream stream = new MemoryStream();
                blob.DownloadToStream(stream);
                long streamlen = stream.Length;
                stream.Position = 0;
                return stream;
            }

        }

public static CloudBlobContainer FindOrCreatePrivateBlobContainer(string ContainerName, string AccountConnectionString)
        {
            Trace.TraceInformation("FindOrCreatePrivateBlobContainer '" + ContainerName + "' with connectionstring '" + AccountConnectionString + "'");
            CloudStorageAccount account = CloudStorageAccount.Parse(AccountConnectionString);
            CloudBlobClient blobClient = account.CreateCloudBlobClient();
            CloudBlobContainer container = blobClient.GetContainerReference(ContainerName);
            container.CreateIfNotExists();
            return container;
        }

我需要一些帮助来解决此错误的原因。我尝试了以下方法:

  1. 检查了要创建的容器的名称是否有效,并且在这种特定情况下仅包含小写字母(没有特殊或大写字符)。
  2. 我了解到 Azure 服务器和调用服务器之间的时区差异会导致 403 禁止错误消息。无论我是从我的个人计算机(时区设置为 UTC)还是从 Azure 部署运行服务,都会发生此错误。
  3. 我检查了我的连接字符串和帐户密钥,这似乎是正确的。格式如下:&lt;add key="MyStuff.DocumentManagement.ConnectionString" value="DefaultEndpointsProtocol=http;AccountName=MyStuffAccount;AccountKey=[obfuscated]" /&gt;
  4. 我试过在http和https之间切换,结果没有区别。
  5. 我可以确认我运行的是最新版本的 Azure 存储 API (4.1.0)
  6. 我可以通过 VS 2013 服务器资源管理器连接到 Azure 存储并创建一个新容器

请帮忙!

更新

这是启用跟踪后的错误输出:应用程序: 2014-07-13T19:08:03 PID[6888] 错误
Microsoft.WindowsAzure.Storage.StorageException:远程服务器 返回错误:(403)禁止。 ---> System.Net.WebException: 远程服务器返回错误:(403)禁止。应用:在 System.Net.HttpWebRequest.GetResponse() 应用程序:在 Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand1 cmd, IRetryPolicy policy, OperationContext operationContext) Application: --- End of inner exception stack trace --- Application: at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand1 cmd, IRetryPolicy 策略, OperationContext operationContext) 应用:在 Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer.Exists(布尔 primaryOnly、BlobRequestOptions requestOptions、OperationContext operationContext) 应用程序:在 Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer.CreateIfNotExists(BlobContainerPublicAccessType accessType、BlobRequestOptions requestOptions、OperationContext operationContext) 应用程序:在 [混淆].DocumentManagement.BlobStorage.BlobHelper.FindOrCreatePrivateBlobContainer(String ContainerName, String AccountConnectionString) 应用程序:在 [混淆].DocumentManagement.BlobStorage.BlobFileItemHandler.GetStream(Int64 FileItemId) 应用程序:请求信息应用程序: 请求ID:fce980ad-a673-4ef1-b55d-d017a49845c8 应用: 申请日期:2014 年 7 月 13 日星期日 19:08:02 GMT 申请: StatusMessage:服务器未能验证请求。确保 Authorization 标头的值正确形成,包括 签名。

【问题讨论】:

  • 您是否能够使用上述代码中使用的相同密钥从 VS 2013 资源管理器访问存储帐户?如果没有,您能否从门户登录并确认您的密钥尚未重新生成。否则,为了帮助进一步调试,您可以运行 fiddler 并在失败发生时共享您的请求的 fiddler 跟踪。
  • @VinayShah-Microsoft 谢谢,这实际上正是问题所在 - 但是我几天前已经解决了这个问题(只是没有时间在这里更新答案)。此密钥生成是否自动发生?
  • 很高兴知道您的问题已解决。密钥重新生成不应自动发生。需要通过门户或服务管理api手动调用。
  • @VinayShah-Microsoft 谢谢。当您凌晨 2 点还在工作时,往往会发生奇怪的事情。

标签: c# asp.net azure-storage


【解决方案1】:

这可能不是这个特定问题的解决方案,但它可能会帮助其他人。

我遇到了 403 错误,很难找到解决方案。我终于发现我的开发机器的时间减少了 2 小时。当我正确设置时间时,403 消失了。

Azure 要求 UTC 时间戳在请求时间的 15 分钟内。

【讨论】:

  • 这也发生在我身上 - 我的网络服务器的国际日期时间服务器同步出现问题。我应用了一个名为 Atomic Clock sync 的工具来更频繁地与国际日期时间服务器同步来解决这个问题。只是想我会把它放在这里,因为我相信一些有这个问题的人可能会在这里结束。
【解决方案2】:

正如我们在上面的 cmets 中所讨论的,当您开始从服务返回 403 状态码时,请确保您的密钥有效。如果通过门户或使用服务管理 API 重新生成密钥,则密钥可能会更改

【讨论】:

    【解决方案3】:

    如果您最近升级了 WindowsAzure.Storage 而不是使用已弃用的 WindowsAzure.StorageClient dll,那么您可能会遇到此问题,因为 BlobRequestOptions 和 OperationContext 尚未设置

    MSDN Link with CloudBlobContainer Create If Not Exists 方法

    http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storage.blob.cloudblobcontainer.createifnotexists.aspx

    【讨论】:

      【解决方案4】:

      我在尝试连接到本地 azure 存储模拟器时遇到了类似的问题。通过 Azure 存储资源管理器连接成功,但通过使用 REST API 的自定义工具,它抛出 403 错误。我必须在配置中手动包含端点并使用 http 而不是 https。

      在此处了解更多信息 (https://docs.microsoft.com/en-us/azure/storage/common/storage-configure-connection-string)

      DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;
      AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;
      BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;
      TableEndpoint=http://127.0.0.1:10002/devstoreaccount1;
      QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;
      

      【讨论】:

        【解决方案5】:

        尝试以下方法: 1. 生成新的访问密钥以在您的 App.config 文件中使用

        或 2. 登录到您的 Azure 门户 在存储帐户下 选择 ->防火墙和虚拟网络 --> 在刀片下,启用允许从“所有网络”选项访问

        我希望这对某人有用!

        enter image description here

        【讨论】:

          【解决方案6】:

          我在调用时看到了同样的错误信息

          Microsoft.WindowsAzure.Storage.Blob.CloudBlobClient.GetBlobReferenceFromServerAsync(Uri blobUri)
          

          意外使用了指向与 CloudBlobClient.BaseUri 所指向的不同 URL 的 blobUri 值。

          【讨论】:

            【解决方案7】:

            对我来说,事实证明我们对存储帐户有 IP 限制,这导致了 403 Forbidden。修复它的方法是访问 Azure 门户并转到:

            存储帐户 → “StorageAccountName” → 防火墙和虚拟网络

            然后确保您的 IP 在允许的部分,或选中“允许从所有网络访问”。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-08-18
              • 2011-05-31
              • 2013-11-28
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多