Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
487 views
in Technique[技术] by (71.8m points)

asp.net - 403 error in production from WindowsAzure.Storage

I have a WebForms app that uses the WindowsAzure.Storage API v3. It works fine in development and in one production environment, but I'm rolling out a new instance and any code that calls out Azure Blob Storage gives me a 403 error.

I've been fiddling with this for awhile, and it fails on any call out to Blob Storage, so rather than show my code I'll show my stack trace:

[WebException: The remote server returned an error: (403) Forbidden.]
   System.Net.HttpWebRequest.GetResponse() +8525404
   Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync(RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext) +1541

[StorageException: The remote server returned an error: (403) Forbidden.]
   Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync(RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext) +2996
   Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer.CreateIfNotExists(BlobContainerPublicAccessType accessType, BlobRequestOptions requestOptions, OperationContext operationContext) +177
   ObsidianData.Azure.Storage.GetContainer(CloudBlobClient client, Containers targetContainer) in D:Dev
SourceObsidianSourceObsidianDataAzureStorage.vb:84
   ObsidianWeb.Leads.HandleListenLink(String fileName, HyperLink link) in D:Dev
SourceObsidianSourceObsidianWebBdcLeads.aspx.vb:188
   ObsidianWeb.Leads.LoadEntity_ContactDetails(BoLead lead) in D:Dev
SourceObsidianSourceObsidianWebBdcLeads.aspx.vb:147
   ObsidianWeb.Leads.LoadEntity(BoLead Lead) in D:Dev
SourceObsidianSourceObsidianWebBdcLeads.aspx.vb:62
   EntityPages.EntityPage`1.LoadEntity() +91
   EntityPages.EntityPage`1.Page_LoadComplete(Object sender, EventArgs e) +151
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +4018

Here's what I've tried...

  • The AzureStorageConnectionString that fails in this environment definitely works in production
  • Other connection strings (from the other production environment, which works) also get a 403 here
  • There seemed to be an issue with timestamps in some old versions of the REST api (which I am not directly using...) so I made certain the times are correct, even tried switching the server to UTC time.
  • Tried toggling the connection string between http/https.
  • Upgraded to the latest version of the API (v3.1)
  • Tried fiddling with the code to ensure that every call out to Azure Storage gets 403. It does.
  • In desperation, Installed Azure Powershell on the server just to verify that some type of communication with Azure is working. And that worked fine.
  • Browsed to the azure management portal as well and that works fine.

Any ideas? This should just be using port 80 or 443, right? So there should be no way this is some kind of network issue. Let me know if that's wrong.

  • The working production machine is an Azure VM (Server 2008 R2 with IIS 7.5) There are also some differences with the server:
  • This new machine is physical hardware (Server 2012 and IIS 8)
  • This IS using a different storage account inside my azure subscription, however I've tried a total of 3 connection strings and none of them work here.

UPDATE: someone asked to see the code. Okay, I wrote a class called Azure.Storage, which just abstracts my cloud storage code. We are failing on a call to Storage.Exists, so here's the part of that class that feels relevant:

    Public Shared Function Exists(container As Containers, blobName As String) As Boolean
        Dim Dir As CloudBlobContainer = GetContainer(container)
        Dim Blob As CloudBlockBlob = Dir.GetBlockBlobReference(blobName.ToLower())

        Return Blob.Exists()
    End Function

    Private Shared Function GetContainer(client As CloudBlobClient, targetContainer As Containers)
        Dim Container As CloudBlobContainer = client.GetContainerReference(targetContainer.ToString.ToLower())
        Container.CreateIfNotExists()
        Container.SetPermissions(New BlobContainerPermissions() With {.PublicAccess = BlobContainerPublicAccessType.Blob})

        Return Container
    End Function

    Private Shared Function GetCloudBlobClient() As CloudBlobClient
        Dim Account As CloudStorageAccount = CloudStorageAccount.Parse(Settings.Cloud.AzureStorageConnectionString())

        Return Account.CreateCloudBlobClient()
    End Function

...Containers is just an enum of container names (there are several):

 Public Enum Containers
     CallerWavs
     CampaignImports
     Delve
     Exports
     CampaignImages
     Logos
     ReportLogos
     WebLinkImages
 End Enum

...Yes, they have upper-case characters, which causes problems. Everything is forced to lowercase before it goes out.

Also I did verify that the correct AzureConnectionString is coming out of my settings class. Again, I tried a few that work elsewhere. And this one works elsewhere also!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Please check the clock on the servers in question. Apart from the incorrect account key, you can also get 403 error if the time on the server is not in sync with the time on storage servers (Give or take +/- 15 minutes deviation is allowed).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...