【问题标题】:Problems handling OnTokenValidated with a delegate assigned in startup.cs使用在 startup.cs 中分配的委托处理 OnTokenValidated 时出现问题
【发布时间】:2018-03-30 19:55:47
【问题描述】:

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

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

public void ConfigureServices(IServiceCollection services)
    {
    services.AddMemoryCache();
    ...
    services.AddScoped<IJwtTokenValidatedHandler, JwtTokenValidatedHandler>();
    // add other services
    ...
    var sp = services.BuildServiceProvider();
    services.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, bOptions =>
        {
            // Configure JwtBearerOptions
            bOptions.Events = new JwtBearerEvents
            {
                OnTokenValidated = sp.GetService<JwtTokenValidatedHandler>().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 中私下声明它。如果可以的话,我更愿意修复这种方法,但我愿意接受其他方法。

【问题讨论】:

    标签: c# dependency-injection asp.net-core


    【解决方案1】:

    考虑继承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<CustomJwtBearerEvents>();
    
            services.AddAuthentication()
                .AddJwtBearer(options =>
                {
                    options.EventsType = typeof(CustomJwtBearerEvents);
                });
        }
    }
    

    【讨论】:

    • 这也将阻止设置为 [AllowAnonymous] 的 API。任何想法如何处理?
    猜你喜欢
    • 2016-05-07
    • 2010-11-18
    • 1970-01-01
    • 1970-01-01
    • 2015-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-14
    相关资源
    最近更新 更多