使用依赖注入替换ASP.NET Core中的JWT承载选项

bra*_*ero 4 c# integration-testing dependency-injection identityserver4 asp.net-core-2.0

在Web 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;
        });
}
Run Code Online (Sandbox Code Playgroud)

BackChannelHandler是的公共财产Startup.cs

public static HttpMessageHandler BackChannelHandler { get; set; }
Run Code Online (Sandbox Code Playgroud)

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

testIdentityServer = new TestServer(identityServerBuilder);
My.Project.Startup.BackChannelHandler = testIdentityServer.CreateHandler();
testApiServer = new TestServer(apiServerBuilder);
Run Code Online (Sandbox Code Playgroud)

尽管此方法运行良好,但我想覆盖DI容器中的services.AddAuthentication()AddJwtBearer(),因此我可以出于测试目的注入身份验证中间件配置,而不是像使用其他依赖项那样使用公共静态属性。当我尝试使用以下方法进行操作时:

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

TestFixture.cs我得到的错误:具有“承载者令牌”的身份验证方案已经存在。

如何正确使用ASP.NET Core?

Mic*_*iey 6

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

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

因此,这是您可以在测试项目中执行的操作:

services.PostConfigure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
{
    options.BackchannelHttpHandler = testIdentityServer.CreateHandler();
});
Run Code Online (Sandbox Code Playgroud)

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