У меня есть приложение WebForms, в котором используется WindowsAzure.Storage API v3. Он отлично работает в разработке и в одной рабочей среде, но я запускаю новый экземпляр, и любой код, который вызывает Azure Blob Storage, дает мне ошибку 403.
Я некоторое время играл с этим, и он не справляется с вызовом Blob Storage, поэтому вместо того, чтобы показывать мой код, я покажу свою трассировку стека:
[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\nSource\Obsidian\Source\ObsidianData\Azure\Storage.vb:84
ObsidianWeb.Leads.HandleListenLink(String fileName, HyperLink link) in D:\Dev\nSource\Obsidian\Source\ObsidianWeb\Bdc\Leads.aspx.vb:188
ObsidianWeb.Leads.LoadEntity_ContactDetails(BoLead lead) in D:\Dev\nSource\Obsidian\Source\ObsidianWeb\Bdc\Leads.aspx.vb:147
ObsidianWeb.Leads.LoadEntity(BoLead Lead) in D:\Dev\nSource\Obsidian\Source\ObsidianWeb\Bdc\Leads.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
Вот что я пробовал...
- AzureStorageConnectionString, которая не работает в этой среде, определенно работает в производстве
- Другие строки подключения (из другой производственной среды, которая работает) также получают здесь 403
- В некоторых старых версиях REST api (которые я непосредственно не использую..., похоже, была проблема с отметками времени), поэтому я убедился, что времена правильные, даже попытались переключить сервер на время UTC.
- Попробовал переключить строку соединения между http/https.
- Обновлена до последней версии API (v3.1)
- Пробовал возиться с кодом, чтобы каждый звонок в Azure Storage получал 403. Он делает.
- В отчаянии Installed Azure Powershell на сервере просто для проверки того, что какой-то тип связи с Azure работает. И это сработало хорошо.
- Также просматривается портал управления azure, и это отлично работает.
Любые идеи? Это должен быть только порт 80 или 443, верно? Поэтому не должно быть никаких проблем с сетью. Сообщите мне, если это неправильно.
- Рабочий производственный станок - это Azure VM (Server 2008 R2 с IIS 7.5) Существуют также некоторые различия с сервером:
- Эта новая машина представляет собой физическое оборудование (Server 2012 и IIS 8).
- Это IS использует другую учетную запись в моей подписке на лазурную печать, однако я пробовал в общей сложности 3 строки подключения, и ни одна из них не работает здесь.
ОБНОВЛЕНИЕ: кто-то попросил посмотреть код. Хорошо, я написал класс под названием Azure.Storage, который просто абстрагирует мой код облачного хранилища. Мы терпим неудачу при вызове Storage.Exists, поэтому вот часть этого класса, которая считает актуальной:
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
... Контейнеры - это просто перечисление имен контейнеров (их несколько):
Public Enum Containers
CallerWavs
CampaignImports
Delve
Exports
CampaignImages
Logos
ReportLogos
WebLinkImages
End Enum
... Да, у них есть символы верхнего регистра, что вызывает проблемы. Все будет зависеть от нижнего регистра, прежде чем он погаснет.
Также я убедился, что корректная AzureConnectionString выходит из моего класса настроек. Опять же, я попробовал несколько, которые работают в другом месте. И это работает и в других местах!