在单例服务中注入 ITokenAcquisition 不适用于 ASPNETCORE_ENVIRONMENT=Development

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

注入 ITokenAcquisition 时我注意到一些奇怪的事情。
您可以在这里找到我的代码来重现该问题:Github Repo
我使用 NuGet Microsoft.Identity.Web 2.18.0 在 ASP.NET Api (.NET 7) 中启用 MSAL 身份验证

我的 Program.cs 看起来像这样:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(builder.Configuration)
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddInMemoryTokenCaches();

// Add services to the container.

builder.Services.AddControllers();
builder.Services.AddHostedService<QueuedHostedService>();
var app = builder.Build();

// Configure the HTTP request pipeline.

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

你可以看到,和我的API一起,后台服务也在运行:

public class QueuedHostedService : BackgroundService
{
    ITokenAcquisition _tokenAcquisition;
    public QueuedHostedService(ITokenAcquisition tokenAcquisition)
    {
        _tokenAcquisition = tokenAcquisition;
    }


    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        await BackgroundProcessing(stoppingToken);
    }

    private async Task BackgroundProcessing(CancellationToken stoppingToken)
    {
        var token = await _tokenAcquisition.GetAccessTokenForAppAsync("api://xxxxx-5a7f-430e-8ea1-6e133055990e/.default");
        while (!stoppingToken.IsCancellationRequested)
        {
            Console.WriteLine("Executing...");
        }
    }

    public override async Task StopAsync(CancellationToken stoppingToken)
    {
        // "Queued Hosted Service is stopping.");

        await base.StopAsync(stoppingToken);
    }
}

此服务使用 ITokenAcquisition 获取另一个 API 的访问令牌(可能是图表等)

我的控制器操作看起来几乎标准,但具有授权属性

[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    ITokenAcquisition _tokenAcquisition;
    public WeatherForecastController(ITokenAcquisition tokenAcquisition) 
    { 
        _tokenAcquisition = tokenAcquisition;
    }

    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    [HttpGet]
    public async Task<IEnumerable<WeatherForecast>> GetAsync()
    {
        var token = await _tokenAcquisition.GetAccessTokenForAppAsync("api://xxxxxx-5a7f-430e-8ea1-6e133055990e/.default");
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        })
        .ToArray();
    }
}

我的代码可以运行,后台服务会收到访问令牌,但前提是 ASPNETCORE_ENVIRONMENT 变量设置为“测试”或“生产”。

在开发中,我的服务失败并显示以下错误消息:

无法使用范围服务 来自单例的“Microsoft.Identity.Web.ITokenAcquisition” 'Microsoft.Extensions.Hosting.IHostedService'。)'

任何人都知道:

  • 是否允许在后台服务中注入ITokenAcquisition?
  • 为什么它可以在测试或生产模式下工作,但不能在开发模式下工作?
c# asp.net-core azure-ad-msal microsoft.identity.web
1个回答
0
投票

像下面那样更改您的

QueuedHostedService.cs
,问题就可以解决。

using Microsoft.Identity.Web;
using static System.Formats.Asn1.AsnWriter;

namespace DataHive.Enterprises.Core.Services
{
    public class QueuedHostedService : BackgroundService
    {
        //ITokenAcquisition _tokenAcquisition;
        private readonly IServiceScopeFactory _scopeFactory;
        public QueuedHostedService(IServiceScopeFactory scopeFactory)
        {
            _scopeFactory = scopeFactory;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            await BackgroundProcessing(stoppingToken);
        }

        private async Task BackgroundProcessing(CancellationToken stoppingToken)
        {
            using (var scope = _scopeFactory.CreateScope())
            {
                var tokenAcquisition = scope.ServiceProvider.GetRequiredService<ITokenAcquisition>();
                var token = await tokenAcquisition.GetAccessTokenForAppAsync("api://0f5ff0f2-5a7f-430e-8ea1-6e133055990e/.default");

                while (!stoppingToken.IsCancellationRequested)
                {
                    Console.WriteLine("Executing...");
                }
            }
        }

        public override async Task StopAsync(CancellationToken stoppingToken)
        {
            // "Queued Hosted Service is stopping.");

            await base.StopAsync(stoppingToken);
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.