0

tl;dr:我正在尝试使用 SAS 从 C# 连接到 Azure BlobStorage,但似乎无法超越StorageException“服务器无法验证请求”的说法。我怀疑我的连接字符串有问题。


我正在使用库Microsoft.Azure.Storage.Blob11.2.3.0 和Microsoft.Azure.Storage.Common11.2.3.0 从 .NET Core 3.1 应用程序连接到 Azure BlobStorage。

我建立此连接的 C# 代码如下所示:

var storageAccount = CloudStorageAccount.Parse(connectionString);
var blobClient = storageAccount.CreateCloudBlobClient();

当使用包含字段AccountNameAccountKeyEndpointSuffixDefaultEndpointsProtocol(this is https) 1的连接字符串时,这可以完美地工作。(我可以连接并执行诸如枚举容器和 blob 之类的操作,还可以创建容器和 blob 并上传数据。)


现在,我应该使用 SAS 连接到同一个 BlobStorage。为此,我得到了以下信息(这里匿名为某种“占位符”,因为我将在下面引用它们):

  • <StorageAccount>AccountName(与上述连接字符串中的字段值相同)
  • <Container>
  • <Blob-SAS-Token>
  • <Blob-SAS-URL>(这实际上由此处找到的其他信息组成,即<DefaultEndpointsProtocol>://<StorageAccount>.blob.<EndpointSuffix>/<Container>?<Blob-SAS-Token>

通过使用上述方法,我可以成功地从Microsoft Azure 存储资源管理器建立到所述 BlobStorage 容器的连接<Blob-SAS-URL>2

但是,到目前为止,我一直无法从我的 C# 代码中成功使用 SAS。

我尝试了各种方法来编写我的连接字符串,例如:

  • BlobEndpoint=<DefaultEndpointsProtocol>://<StorageAccount>.blob.<EndpointSuffix>;SharedAccessSignature=<Blob-SAS-Token>
  • BlobEndpoint=<DefaultEndpointsProtocol>://<StorageAccount>.blob.<EndpointSuffix>/<Container>;SharedAccessSignature=<Blob-SAS-Token>

根据文档,这应该有效。在那里,基于 SAS 的连接字符串被概述为包含最多五个字段 - BlobEndpointQueueEndpointTableEndpointFileEndpointSharedAccessSignature- 其中只有(任何)四个端点中的一个必须在 SAS 旁边指定。

我还尝试过创建/填充CloudStorageAccount实例,而不是通过(可能是格式错误的)连接字符串,例如:

var storageAccount = new CloudStorageAccount(
    new StorageCredentials("<Blob-SAS-Token>"),
    "<StorageAccount>", "<EndpointSuffix>", true);

不幸的是,无论我尝试什么,只要我尝试以这种方式从 BlobStorage 检索任何数据,Microsoft.Azure.Storage.StorageException就会抛出 a,说明

服务器未能验证请求。确保 Authorization 标头的值正确形成,包括签名。

我本地机器上的 UTC 时间与我可以在在线资源上找到的当前 UTC 时间完全匹配。因为我可以从同一台机器上的另一个应用程序连接我的 SAS 信息,所以问题很可能与环境的任何方面无关(例如在某些阻止列表或类似列表中缺少我的 IP 地址条目)。相反,我怀疑我没有提供足够的信息来建立连接。

我必须进行哪些更改才能使此连接正常工作?


1:我将在这篇文章中使用各种标识符和凭据的某种“占位符”,以免泄露任何机密信息。我希望这不会太混乱。另一方面,它实际上应该允许通过几个查找和替换操作轻松地将信息调整到可用的样本端点。

2:为此,我右键单击存储帐户树节点,然后连接到 Azure 存储... > Blob 容器> SAS URL(共享访问签名

4

1 回答 1

0

下面基于连接字符串的解决方案。

根据Swetha 的评论,我能够使用以下代码进行连接:

var creds = new StorageCredentials("<Blob-SAS-Token>");
var blobContainer = new CloudBlobContainer(new Uri("<DefaultEndpointsProtocol>://<StorageAccount>.blob.<EndpointSuffix>/<Container>"), creds);

然后我可以从/向 检索和上传数据blobContainer

不幸的是,这意味着连接到 BlobStorage 的代码看起来与连接字符串不同。因此,我需要提供、测试和维护两个不同的代码路径,具体取决于提供了哪种连接配置(并且不能保证第三种身份验证方法不需要另一个代码路径 - 我现在已经问过关于在一个单独的问题中)。


更新:根据对我关于存储连接数据的问题的回答,我现在了解到实际上可以使用连接字符串与 SAS 连接。以下格式已被证明是有效的:

  • BlobEndpoint=<DefaultEndpointsProtocol>://<StorageAccount>.blob.<EndpointSuffix>;SharedAccessSignature=<Blob-SAS-Token>
  • DefaultEndpointsProtocol=<DefaultEndpointsProtocol>;EndpointsSuffix=<EndpointsSuffix>;SharedAccessSignature=<Blob-SAS-Token>

然后,重要的一点是(至少如果 SAS 是特定于容器的,就像我得到的那样 - 我不确定情况总是如此)我可以容器中工作,但不能容器上工作(或任何外部其中)。那是:

  • CloudBlobContainer虽然我可以通过将容器名称传递给来检索实例GetContainerReference,但我无法调用ListContainers(这会引发异常,而不是仅枚举我可以使用 SAS 访问的容器集)。
  • 我必须假设容器已经存在。在容器上调用时两者Exists()都会抛出异常。1CreateIfNotExists()

一旦坚持这些限制,就可以CloudStorageAccount.Parse(connectionString)再次使用。


1:我创建了一个关于如何安全检查容器是否存在的单独问题

于 2021-11-26T08:24:09.327 回答