据我所知,具有单独身份验证模式的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
)短路的情况下,该对象被处置。那我的错误在哪里?
答案 0 :(得分:0)
我可以为您解决小问题。不会为每个请求调用Configure
方法。 var localDbContext = services.GetService<CollegeLocalDbContext>();
行仅在第一次执行。在第二个请求下,仅匿名方法async (context, next)
将被触发,当然,现在您将没有任何localDbContext
设置。