使用依赖注入替换 ASP.NET Core 中的 JWT Bearer Options

Using dependency injection to replace JWT Bearer Options in ASP.NET Core

在网络 API 中,我使用 Jwt Auth 进行保护,我有以下 ConfigureServices Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(this.Configuration.GetConnectionString("DefaultConnection")));
    // Some additional application dependencies here with AddTransient()...
    services.AddMvc();
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
           options.Authority = "xxxxx";
           options.RequireHttpsMetadata = false;
           options.Audience = "xxxxx";
           options.BackchannelHttpHandler = BackChannelHandler;
        });
}

这里,BackChannelHandlerStartup.cs的public属性:

public static HttpMessageHandler BackChannelHandler { get; set; }

我使用这个 属性 的原因是当我使用 xUnit 进行集成测试时,我使用的是 Microsoft.AspNetCore.TestHost 的内存中 TestServer。所以,我需要在 TestFixture class 中注册反向通道处理程序,例如

testIdentityServer = new TestServer(identityServerBuilder);
My.Project.Startup.BackChannelHandler = testIdentityServer.CreateHandler();
testApiServer = new TestServer(apiServerBuilder);

虽然这工作正常,但我想覆盖 DI 容器中的 services.AddAuthentication()AddJwtBearer(),因此我可以注入身份验证中间件配置以进行测试,而不是使用 public static 属性 就像我处理任何其他依赖项一样。当我尝试使用以下方法执行此操作时:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
       options.Authority = "xxxxx";
       options.RequireHttpsMetadata = false;
       options.Audience = "xxxxx";
       options.BackchannelHttpHandler = testIdentityServer.CreateHandler();
    });

TestFixture.cs 中我收到错误消息:"Bearer token" 的身份验证方案已经存在。

如何使用 ASP.NET Core 正确执行此操作?

您遇到的行为是正常的,因为同一身份验证方案不能有 2 个处理程序。这里,AddJwtBearer 为身份验证方案 Bearer 添加了一个处理程序,该值来自 JwtBearerDefaults.AuthenticationScheme.

您传递给 AddJwtBearer 的 lambda 表达式被注册为命名选项配置,它注册的名称是身份验证方案。

下面是您可以在测试项目中执行的操作:

services.PostConfigure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
{
    options.BackchannelHttpHandler = testIdentityServer.CreateHandler();
});

这样做不会更改已在容器中注册的身份验证方案,只会修改与 JWT 处理程序关联的选项。