26

我曾经能够使用 v11 Azure SDK API 在 Blob 上创建共享访问签名,如下所示:

var containerName = "mycontainer";
var blobName = "myblob";

CloudStorageAccount storageAccount 
 = CloudStorageAccount.Parse(<StorageConnectionString>);

CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

CloudBlobContainer container = blobClient.GetContainerReference(containerName);


SharedAccessBlobPermissions permission = SharedAccessBlobPermissions.Read;

TimeSpan clockSkew = TimeSpan.FromMinutes(15d);
TimeSpan accessDuration = TimeSpan.FromMinutes(15d);

var blobSAS = new SharedAccessBlobPolicy
{
    SharedAccessStartTime = DateTime.UtcNow.Subtract(clockSkew),
    SharedAccessExpiryTime = DateTime.UtcNow.Add(accessDuration) + clockSkew,
    Permissions = permissions
};

CloudBlockBlob blob = container.GetBlockBlobReference(blobName);

string sasBlobToken = blob.GetSharedAccessSignature(blobSAS);

...

我想使用最新的 v12 .NET API,它似乎替换CloudBlobClientBlobServiceClientCloudBlobContainerbyBlobContainerClientCloudBlockBlobby BlobClient

但是,在实例GetSharedAccessSignature上可用的方法在CloudBlockBlob实例上不可用BlobClient

问题

如何BlobClient使用最新的 Azure SDK .NET API v12 从实例获取共享访问签名?

4

6 回答 6

37

Sajeetharan 的回答让我寻找一个实际存在的BlobSasBuilder类。

以下是我如何在服务器上构建一个:

//  Creates a client to the BlobService using the connection string.
var blobServiceClient = new BlobServiceClient(storageConnectionString);

//  Gets a reference to the container.
var blobContainerClient = blobServiceClient.GetBlobContainerClient(<ContainerName>);

//  Gets a reference to the blob in the container
BlobClient blobClient = containerClient.GetBlobClient(<BlobName>);

//  Defines the resource being accessed and for how long the access is allowed.
var blobSasBuilder = new BlobSasBuilder
{
    StartsOn = DateTime.UtcNow.Subtract(clockSkew), 
    ExpiresOn = DateTime.UtcNow.Add(accessDuration) + clockSkew,
    BlobContainerName = <ContainerName>,
    BlobName = <BlobName>,
};
    
//  Defines the type of permission.
blobSasBuilder.SetPermissions(BlobSasPermissions.Write);
       
//  Builds an instance of StorageSharedKeyCredential      
var storageSharedKeyCredential = new StorageSharedKeyCredential(<AccountName>, <AccountKey>);

//  Builds the Sas URI.
BlobSasQueryParameters sasQueryParameters = blobSasBuilder.ToSasQueryParameters(storageSharedKeyCredential);

以下是如何在客户端使用它:

//  Builds the URI to the blob storage.
UriBuilder fullUri = new UriBuilder()
{
    Scheme = "https",
    Host = string.Format("{0}.blob.core.windows.net", <AccountName>),
    Path = string.Format("{0}/{1}", <ContainerName>, <BlobName>),
    Query = sasQueryParameters.ToString()
};

//  Get an instance of BlobClient using the URI.
var blobClient = new BlobClient(fullUri.Uri, null);

//  Upload stuff in the blob.
await blobClient.UploadAsync(stream);

附录

正如@one2012 在评论中提到的那样,在这个答案之后几个月后,一个页面已经出现,展示了 Azure.Storage 命名空间中的所有功能。该链接可用于获取更多信息。

更新

在服务器端,我有一个 Azure 函数,它现在将 Azure 存储与函数的托管标识连接起来。当我连接存储时,我不再使用帐户,只使用存储的端点:

BlobContainerClient blobContainerClient = new(new Uri(containerEndpoint), new DefaultAzureCredential());  

这使得初始服务器代码的以下部分有点棘手,因为我曾经使用该CloudStorageAccount.Credentials.GetExportKeys()方法来获取帐户的密钥。使用托管身份时,我似乎无法再访问它了:

//  Builds an instance of StorageSharedKeyCredential      
    var storageSharedKeyCredential = new StorageSharedKeyCredential(<AccountName>, <AccountKey>);

事实证明,我必须使用用户委派来构建 SAS Uri:

...
BlobServiceClient blobServiceClient = blobClient.GetParentBlobContainerClient().GetParentBlobServiceClient();

UserDelegationKey userDelegationKey = await blobServiceClient.GetUserDelegationKeyAsync
(
    DateTimeOffset.UtcNow,
    DateTimeOffset.UtcNow.AddMinutes(5d)
);
            
BlobUriBuilder blobUriBuilder = new (blobClient.Uri)
{
    // Specify the user delegation key.
    Sas = blobSasBuilder.ToSasQueryParameters(userDelegationKey, blobServiceClient.AccountName)
};

string uri = blobUriBuilder.ToUri();

    
于 2019-12-01T11:47:12.597 回答
9

经过大量搜索后,我找到了一些 Microsoft 文档:https ://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-user-delegation-sas-create-dotnet

此详细信息使用用户委托密钥生成 SAS 而不是帐户密钥,但更改只是 .ToSasQueryParameters() 的不同重载,如其他答案中所述。

文章中的一些关键片段将其连接起来。首先创建您的 BlobServiceClient:

// Construct the blob endpoint from the account name.
string blobEndpoint = string.Format("https://{0}.blob.core.windows.net", accountName);

// Create a new Blob service client with Azure AD credentials.
BlobServiceClient blobClient = new BlobServiceClient(new Uri(blobEndpoint),
                                                     new DefaultAzureCredential());

获取用户授权密钥,这将用于生成 SAS:

// Get a user delegation key for the Blob service that's valid for seven days.
// You can use the key to generate any number of shared access signatures over the lifetime of the key.
UserDelegationKey key = await blobClient.GetUserDelegationKeyAsync(DateTimeOffset.UtcNow,
                                                                   DateTimeOffset.UtcNow.AddDays(7));

最后创建 SAS URI:

// Create a SAS token that's valid for one hour.
BlobSasBuilder sasBuilder = new BlobSasBuilder()
{
    BlobContainerName = containerName,
    BlobName = blobName,
    Resource = "b",
    StartsOn = DateTimeOffset.UtcNow,
    ExpiresOn = DateTimeOffset.UtcNow.AddHours(1)
};

// Specify read permissions for the SAS.
sasBuilder.SetPermissions(BlobSasPermissions.Read);

// Use the key to get the SAS token.
string sasToken = sasBuilder.ToSasQueryParameters(key, accountName).ToString();

// Construct the full URI, including the SAS token.
UriBuilder fullUri = new UriBuilder()
{
    Scheme = "https",
    Host = string.Format("{0}.blob.core.windows.net", accountName),
    Path = string.Format("{0}/{1}", containerName, blobName),
    Query = sasToken
};
于 2020-01-29T18:13:12.747 回答
3

使用适用于 .NET 的 Azure Blob 存储客户端库 v12:

BlobSasBuilder blobSasBuilder = new BlobSasBuilder()
{
    BlobContainerName = blobContainerName,
    BlobName = blobName,
    Resource = "b", //b = blob, c = container
    StartsOn = DateTimeOffset.UtcNow,
    ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(lifetimeMinutes)
};

blobSasBuilder.SetPermissions(BlobSasPermissions.Read);

StorageSharedKeyCredential storageSharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);

string sas = blobSasBuilder.ToSasQueryParameters(storageSharedKeyCredential).ToString();

如果必须根据分配给容器的访问策略生成共享访问签名(SAS 令牌),请使用以下方法

BlobSasBuilder blobSasBuilder = new BlobSasBuilder()
{
    BlobContainerName = blobContainerName,
    BlobName = blobName,
    Resource = "b", //b = blob, c = container
    Identifier = "ReadOnlyPolicy" //string value referees to the access policy created and assigned to the container.
};

StorageSharedKeyCredential storageSharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);

string sas = blobSasBuilder.ToSasQueryParameters(storageSharedKeyCredential).ToString();

注意:当 SAS 令牌生成基于分配给容器的访问策略时,您将无法在 BlobSasBuilder 中定义权限、开始或结束时间。您将收到运行时异常,因为“访问策略字段可以与签名或 SAS 标识符相关联,但不能同时与两者相关联”

参考:https ://www.craftedforeveryone.com/beginners-guide-and-reference-to-azure-blob-storage-sdk-v12-dot-net-csharp/

https://www.craftedforeveryone.com/beginners-guide-and-reference-to-azure-blob-storage-sdk-v12-dot-net-csharp/#generate_access_policy_based_sas_token_for_a_blob

于 2020-05-14T10:10:49.600 回答
1

在这里:https : //docs.microsoft.com/en-us/rest/api/storageservices/delegate-access-with-shared-access-signature 表明 Azure 存储支持三种不同类型的共享访问签名 (SAS) :

  1. 帐户级别 SAS,这是您在 v11 SDK 中使用的。此处的详细信息和示例:https ://docs.microsoft.com/en-us/azure/storage/common/storage-account-sas-create-dotnet
  2. 服务级别 SAS,使用 v12 (& V11) SDK。此处的详细信息和示例:https ://docs.microsoft.com/en-us/azure/storage/blobs/sas-service-create?tabs=dotnet
  3. 用户委托 SAS,这是 Microsoft 推荐的方法,前提是您可以使用 Azure Active Directory 用户使用 v12 SDK 进行签名。此处的详细信息和示例:https ://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-user-delegation-sas-create-dotnet

1 和 2 都使用帐户的共享密钥来生成 SAS 令牌,而 3 使用从 AAD 帐户用户生成的密钥,因此在需要时更安全且更容易撤销(理论上)。请参阅https://docs.microsoft.com/en-us/rest/api/storageservices/create-user-delegation-sas#:~:text=Authorization%20of%20a%20user%20delegation%20SAS,-When%20a %20client&text=这个%20approach%20provides%20an%20additional,是%20a%20security%20best%20practice。有关为什么这更安全的更多详细信息(“这种方法提供了额外的安全级别,并且避免了将帐户访问密钥与应用程序代码一起存储的需要。出于这些原因,使用 Azure AD 凭据创建 SAS 是一种安全最佳实践.")

现在所有存储帐户都支持使用,但我得到的印象是帐户级别要么不支持在 v12 SDK 中实现(我在猜测 - 所以不要引用我,但我也找不到这个) 或者有一些其他隐藏的方法来做到这一点(当然 BlobSasBuilder.ToSasQueryParameters() 方法只有两个重载),我猜这将用户委托或服务级别方法保留为您现在打算实现的方法。

于 2020-11-12T13:01:58.780 回答
0

使用适用于 .NET 的 Azure Blob 存储客户端库 v12:

        BlobSasBuilder blobSasBuilder = new BlobSasBuilder()
        {
            BlobContainerName = blobContainerName,
            BlobName = blobName,
            Resource = "b", //b = blob, c = container
            StartsOn = DateTimeOffset.UtcNow,
            ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(lifetimeMinutes)
        };

        blobSasBuilder.SetPermissions(BlobSasPermissions.Read);

        StorageSharedKeyCredential storageSharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);

        string sas = blobSasBuilder.ToSasQueryParameters(storageSharedKeyCredential).ToString();
于 2019-12-05T20:10:39.340 回答
0
private string BuildSASUri(BlobClient blob)
{
    // Create a user SAS that only allows reading for a minute
    BlobSasBuilder sas = new BlobSasBuilder 
    {
        BlobContainerName = blob.BlobContainerName,
        BlobName = blob.Name,
        Resource = "b",
        ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(1)
    };
    // Allow read access
    sas.SetPermissions(BlobSasPermissions.Read);
    var storageSharedKeyCredential = new StorageSharedKeyCredential(
        _iconfiguration.GetValue<string>("StorageAccount:AccountName"),
        _iconfiguration.GetValue<string>("StorageAccount:AccountKey")
    );

    return sas.ToSasQueryParameters(storageSharedKeyCredential).ToString();
}

以上是我的工作代码。

但是,我不知道如何使用 V12 创建存储访问策略。应该是这样的:https ://docs.microsoft.com/en-us/dotnet/api/azure.storage.blobs.blobcontainerclient.setaccesspolicy?view=azure-dotnet

但我认为微软已经完全忘记了提供一种创建 BlobSignedIdentifier 的方法。

文档已过时:https://docs.microsoft.com/en-us/azure/storage/common/storage-stored-access-policy-define-dotnet?toc=%2fazure%2fstorage%2fblobs%2ftoc。 json

它使用 Microsoft.Azure.Storage.Blob,但https://www.nuget.org/packages/Microsoft.Azure.Storage.Blob/说不要再使用它了。

于 2020-01-07T19:42:32.283 回答