Azure DefaultAzureCredential 在本地 Visual Studio 中失败

问题描述 投票:0回答:1

我们在 Azure 环境中使用 Azure 系统分配的托管身份来对 Azure 云资源之间的调用进行身份验证。

我们在注册

DefaultAzureCredential 
时尝试实现
BlobServiceClient

        services.AddAzureClients(builder =>
        {

            builder.UseCredential(new DefaultAzureCredential());

            string url = string.Format("https://{0}.blob.core.windows.net/{1}",
                                                       blobStorageOptions.AccountName,
                                                       blobStorageOptions.ContainerName);
            builder.AddBlobServiceClient(new Uri(url));
        });

根据 文档

DefaultAzureCredential
应执行各种
TokenCredential
实现,直到其中之一成功。 如果没有成功,则会抛出
CredentialUnavailableException

DefaultAzureCredential
身份验证的默认顺序是在调用
ManagedIdentityCredential
之前调用
VisualStudioCredential
。 因此,当应用程序在本地 VS 中运行时,
ManagedIdentityCredential
should 会失败,而
VisualStudioCredential
最终成功并且代码按设计运行。

但是,应用程序会在本地失败,并在调用

CredentialUnavailableException
时抛出
ManagedIdentityCredential
,而不是继续执行应该成功的
VisualStudioCredential
。 当应用程序部署到我们的 Azure 环境时,它就会成功。 请注意,我们的 VS Tools>Options>AzureServiceAuthentication 已正确配置,并且帐户具有所需的权限。

我们也用过这个方法:

        services.AddAzureClients(builder =>
        {
            TokenCredential credential = new ChainedTokenCredential(
                new ManagedIdentityCredential(),
                new VisualStudioCredential());

            builder.UseCredential(credential);

            string url = string.Format("https://{0}.blob.core.windows.net/{1}",
                                                       blobStorageOptions.AccountName,
                                                       blobStorageOptions.ContainerName);
            builder.AddBlobServiceClient(new Uri(url));
        });

如此处推荐的 适用于 .NET 的 Azure 身份库中的凭据链(以获得更好的性能)。

这也会以同样的方式在本地失败(

ManagedIdentityCredential
抛出异常)。

如果我们更改前面代码的顺序(

VisualStudioCredential
ManagedIdentityCredential
之前),应用程序在本地和Azure环境中都会成功:

            TokenCredential credential = new ChainedTokenCredential(
                new VisualStudioCredential(),
                new ManagedIdentityCredential());

我们可以使用之前的实现,但是文档中描述的效率提升将无法实现。

我唯一的结论是

DefaultAzureCredential
没有按设计工作。我是不是错过了什么?

azure defaultazurecredential
1个回答
0
投票

我尝试使用以下代码在 Azure 门户中使用

DefaultAzureCredential
ManagedIdentityCredential
在本地对 Azure 存储进行身份验证。

我已将 Storage Blob Data Contributor 角色分配给 Azure 存储中的

Service Principal
Web App
,以避免出现下面所示的错误。

enter image description here

程序.cs:

using Azure.Core;
using Azure.Identity;
using Microsoft.Extensions.Azure;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddSwaggerGen();
builder.Services.AddAzureClients(clientBuilder =>
{
    TokenCredential credential;
    if (builder.Environment.IsDevelopment())
    {
        credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions
        {
        });
    }
    else
    {
        credential = new ManagedIdentityCredential();
    }

    clientBuilder.UseCredential(credential);

    string blobUri = "https://<StorageName>.blob.core.windows.net";
    clientBuilder.AddBlobServiceClient(new Uri(blobUri));
});
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "Web API V1");
    c.RoutePrefix = app.Environment.IsDevelopment() ? "swagger" : string.Empty;
});
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();

BlobController.cs:

using Azure.Storage.Blobs;
using Microsoft.AspNetCore.Mvc;

namespace WebApplication19.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class BlobController : ControllerBase
    {
        private readonly BlobServiceClient _blobServiceClient;
        public BlobController(BlobServiceClient blobServiceClient)
        {
            _blobServiceClient = blobServiceClient;
        }
        [HttpGet("list-blobs")]
        public async Task<IActionResult> ListBlobsAsync()
        {
            try
            {
                var containerClient = _blobServiceClient.GetBlobContainerClient("kamcontainer");
                var blobItems = new List<string>();
                await foreach (var blobItem in containerClient.GetBlobsAsync())
                {
                    blobItems.Add(blobItem.Name);
                }
                return Ok(blobItems);
            }
            catch (Exception ex)
            {
                return StatusCode(500, $"Internal server error: {ex.Message}");
            }
        }
    }
}

本地输出:

存储 Blob 数据贡献者角色分配给服务主体后,我成功检索了 Blob 列表。

enter image description here

Azure Web 应用程序输出:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.