使用身份核心控制用户登录

时间:2020-08-17 07:25:15

标签: authentication .net-core asp.net-identity

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

        [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();
            ...
        }

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

主要:我应该如何中断身份验证作业?我已经测试过清空context.User,但目前无法正常工作。

次要:在使用if (true || ...)的if(localDbContext)短路的情况下,该对象被处置。那我的错误在哪里?

1 个答案:

答案 0 :(得分:0)

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