如何使用SAS令牌从C#连接到Azure BlobStorage? [英] How to use SAS Token to connect to Azure BlobStorage from C#?
问题描述
tl;dr:我正在尝试使用SAS从C#连接到Azure BlobStorage,但似乎无法通过StorageException
说明服务器无法对请求进行身份验证。我怀疑我的连接字符串有问题。
我正在使用库Microsoft.Azure.Storage.Blob
11.2.3.0和Microsoft.Azure.Storage.Common
11.2.3.0从.NET Core 3.1应用程序连接到Azure BlobStorage。
建立此连接的C#代码如下:
var storageAccount = CloudStorageAccount.Parse(connectionString);
var blobClient = storageAccount.CreateCloudBlobClient();
当使用包含AccountName
、AccountKey
、EndpointSuffix
和DefaultEndpointsProtocol
(这是https
)1字段的连接字符串时,它可以完美地工作。(我可以连接并执行枚举容器和BLOB之类的操作,还可以创建容器和BLOB并上传数据。)
现在,我应该使用SAS连接到相同的BlobStorage。为此,我得到了以下几点信息(这里匿名给某种占位符,因为我将在下面引用它们):
<StorageAccount>
(与上述连接字符串中AccountName
字段的值相同)<Container>
<Blob-SAS-Token>
<Blob-SAS-URL>
(这实际上是由这里找到的其他信息组成的,即<DefaultEndpointsProtocol>://<StorageAccount>.blob.<EndpointSuffix>/<Container>?<Blob-SAS-Token>
)
我可以使用上述<Blob-SAS-URL>
从Microsoft Azure Storage Explorer成功建立到所述BlobStorage容器的连接。2
但是,到目前为止,我还无法从C#代码成功使用SAS。
我尝试了多种方式来编写连接字符串,例如:
BlobEndpoint=<DefaultEndpointsProtocol>://<StorageAccount>.blob.<EndpointSuffix>;SharedAccessSignature=<Blob-SAS-Token>
BlobEndpoint=<DefaultEndpointsProtocol>://<StorageAccount>.blob.<EndpointSuffix>/<Container>;SharedAccessSignature=<Blob-SAS-Token>
根据docs,此应起作用。其中,概述了一个基于SAS的连接字符串,它最多包含五个字段-BlobEndpoint
、QueueEndpoint
、TableEndpoint
、FileEndpoint
和SharedAccessSignature
,其中在SAS旁边必须指定四个端点之一。
我还尝试以不同于使用(可能格式错误的)连接字符串的方式创建/填充CloudStorageAccount
实例,例如:
var storageAccount = new CloudStorageAccount(
new StorageCredentials("<Blob-SAS-Token>"),
"<StorageAccount>", "<EndpointSuffix>", true);
遗憾的是,无论我如何尝试,只要我尝试以这种方式从BlobStorage检索任何数据,就会抛出一个Microsoft.Azure.Storage.StorageException
,声明
我本地计算机上的UTC时间与我可以在在线资源上找到的当前UTC时间完全一致。因为我可以从同一台计算机上的另一个应用程序连接到我的SAS信息,所以这个问题很可能与环境的任何方面无关(例如,我的IP地址在某个阻止列表或类似列表中丢失了条目)。相反,我怀疑我没有提供建立连接所需的足够信息。服务器无法对请求进行身份验证。请确保包括签名在内的授权标头的值格式正确。
要使此连接正常工作,我必须更改什么?
1:为了不泄露任何机密信息,我将使用某种占位符和凭据来写这篇文章。我希望这不会太令人困惑。另一方面,它实际上应该允许通过几个查找和替换操作轻松地使信息适应可用的任何样本端点。
2:为此,我右键单击存储帐户树节点,然后连接到Azure存储...&>Blob容器&SAS URL(共享访问签名
推荐答案
基于连接字符串的解决方案如下。
基于Swetha's comment,我能够使用以下代码进行连接:
var creds = new StorageCredentials("<Blob-SAS-Token>");
var blobContainer = new CloudBlobContainer(new Uri("<DefaultEndpointsProtocol>://<StorageAccount>.blob.<EndpointSuffix>/<Container>"), creds);
然后我可以从blobContainer
检索数据并将数据上载到blobContainer
。
更新:基于an answer to my question about storing connection data,我现在了解到实际上可以使用连接字符串与SA连接。以下格式已被证明有效:
BlobEndpoint=<DefaultEndpointsProtocol>://<StorageAccount>.blob.<EndpointSuffix>;SharedAccessSignature=<Blob-SAS-Token>
DefaultEndpointsProtocol=<DefaultEndpointsProtocol>;EndpointsSuffix=<EndpointsSuffix>;SharedAccessSignature=<Blob-SAS-Token>
然后,重要的一点是(至少如果SA是特定于容器的--我不确定是否总是这样),我可以在容器中工作,但不能在容器(或容器外的任何东西)上工作。即:
- 虽然我可以通过将容器名称传递给
GetContainerReference
来检索CloudBlobContainer
实例,但我不能调用ListContainers
(这会引发异常,而不是仅枚举我可以使用SA访问的容器集)。 - 我必须假定容器已经存在。
Exists()
和CreateIfNotExists()
在容器上调用时都会引发异常。1
一旦遵守这些限制,就可以再次使用CloudStorageAccount.Parse(connectionString)
。
1:我已创建了一个separate question about how to safely check for a container's existence。
这篇关于如何使用SAS令牌从C#连接到Azure BlobStorage?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!