使用依赖注入替换 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;
});
}
这里,BackChannelHandler
是Startup.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 处理程序关联的选项。
在网络 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;
});
}
这里,BackChannelHandler
是Startup.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 处理程序关联的选项。