使用在startup.cs中分配的委托处理OnTokenValidated的问题

我想在ASP.NET Core 2.0中正确使用DI,以便让我的自定义方法处理在身份validation期间validationJWT令牌后触发的OnTokenValidated事件。 下面的解决方案有效, 除了在处理程序中我使用一个注入的服务来命中MemoryCache来检查控制器中其他位置添加的缓存项(我已经validation它们已被添加和保留),并且当它被访问时,缓存是总是空的。 我怀疑这是因为我的自定义处理程序对象是由不同的容器创建的(由于早期的BuildServiceProvider()调用?)并且正在使用MemoryCache (或类似的)的单独实例。

如果是这种情况,我想我不清楚如何在startup.cs中的ConfigureServices()中正确添加和引用我的类和方法,以便它按预期工作。 这就是我所拥有的:

 public void ConfigureServices(IServiceCollection services) { services.AddMemoryCache(); ... services.AddScoped(); // add other services ... var sp = services.BuildServiceProvider(); services.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, bOptions => { // Configure JwtBearerOptions bOptions.Events = new JwtBearerEvents { OnTokenValidated = sp.GetService().JwtTokenValidated }; } 

我的自定义处理程序类如下。 ValidateSessionAsync()调用使用注入的AppSessionService访问MemoryCache对象并确保存在缓存条目:

 public class JwtTokenValidatedHandler : IJwtTokenValidatedHandler { AppSessionService _session; public JwtTokenValidatedHandler(AppSessionService session) { _session = session; } public async Task JwtTokenValidated(TokenValidatedContext context) { // Add the access_token as a claim, as we may actually need it var accessToken = context.SecurityToken as JwtSecurityToken; if (Guid.TryParse(accessToken.Id, out Guid sessionId)) { if (await _session.ValidateSessionAsync(sessionId)) { return; } } throw new SecurityTokenValidationException("Session not valid for provided token."); } } 

如果自定义OnTokenValidated方法包含简单逻辑并且不需要注入服务,我将使用匿名函数对其进行内联,或者在startup.cs中私下声明它。 如果可以的话,我宁愿修改这种方法,但我会对其他方法持开放态度。

而不是使用static / singleton事件,考虑JwtBearerEvents并使用JwtBearerOptions.EventsType选项:

 public class CustomJwtBearerEvents : JwtBearerEvents { AppSessionService _session; public CustomJwtBearerEvents(AppSessionService session) { _session = session; } public override async Task TokenValidated(TokenValidatedContext context) { // Add the access_token as a claim, as we may actually need it var accessToken = context.SecurityToken as JwtSecurityToken; if (Guid.TryParse(accessToken.Id, out Guid sessionId)) { if (await _session.ValidateSessionAsync(sessionId)) { return; } } throw new SecurityTokenValidationException("Session not valid for provided token."); } } public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddScoped(); services.AddAuthentication() .AddJwtBearer(options => { options.EventsType = typeof(CustomJwtBearerEvents); }); } }