首页 > 解决方案 > 使用身份核心控制用户登录

问题描述

据我所知,具有个人身份验证模式的身份核心使用 JWT 标准进行身份验证。Hense JWT 是无状态的,它不保留任何有关用户登录的数据。现在我想如果用户第二次登录,则使先前生成的令牌无效。因此,我已在此链接中阅读了有关此内容的信息,并尝试节省生成令牌的时间,并将该时间作为自定义声明存储到令牌本身中。我已经达到了以下几点:

        [HttpPost("login")]
        public async Task<ActionResult> Login([FromBody] User_Login model)
        {
                ...
                await this.updateLastLogin(user.Id, now);
                ...
        }

        private async Task updateLastLogin(string UserId, DateTime now)
        {
            localDbContext.TokenTimeStamps.RemoveRange(localDbContext.TokenTimeStamps.Where(tts => tts.UserId == UserId));
            localDbContext.TokenTimeStamps.Add(new TokenTimeStamp(){
                TimeStamp = now.ToString("yyyyddMMHHmmssfff"),
                UserId = UserId,
            });
            localDbContext.SaveChanges();
            dbContext.Users.First(usr => usr.Id == UserId)
                .LastLoginDateTime = now;
            dbContext.SaveChangesAsync();
        }

现在使用这些代码行,我已经保存了时间戳,以便稍后在身份验证步骤中检查它。现在我正在尝试在中间件中完成这项工作。所以我在 Startup.cs 中写了以下内容:

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            ...
            app.UseAuthentication();
            using (var serviceScope = app.ApplicationServices.CreateScope())
            {
                var services = serviceScope.ServiceProvider;
                var localDbContext = services.GetService<CollegeLocalDbContext>();

                app.Use(async (context, next) =>
                {
                    var authorizationHeader = context.Request.Headers["Authorization"];
                    if (!string.IsNullOrWhiteSpace(authorizationHeader))
                    {
                        Console.WriteLine(authorizationHeader);
                        var UserId = context.User.Identity.Name;
                        var LastLoginDateTime = context.User.Claims.FirstOrDefault(clm => clm.Type == "LastLoginDateTime");
                        Console.WriteLine($"{UserId} - {LastLoginDateTime?.Value}");
                        if (
                            true
                            // || LastLoginDateTime == null || !localDbContext.TokenTimeStamps.Any(tts => tts.TimeStamp == LastLoginDateTime.Value && tts.UserId == UserId)
                        )
                        {
                            context.User = null;
                            return;
                        }
                    }

                    // Call the next delegate/middleware in the pipeline
                    await next();
                });
            }
            app.UseAuthorization();
            ...
        }

现在我有一个主要和一个小问题要解决:

Major:我应该如何破坏身份验证工作?我已经测试清空context.User,但它不会正常工作。

Minor:if (true || ...)在使用时if()短路的情况下localDbContext,表示该对象已被处理。那么我的错误在哪里?

标签: authentication.net-coreasp.net-identity

解决方案


我可以帮你解决小问题。Configure不会为每个请求调用该方法。行:var localDbContext = services.GetService<CollegeLocalDbContext>();将仅在第一次执行。在第二个请求中,只会async (context, next)触发匿名方法,当然现在您将没有任何localDbContext设置。


推荐阅读