据我所知,具有单独身份验证模式的Identity core使用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();
...
}
现在我有一个大问题和一个小问题要解决:
专业:我应该如何破坏身份验证作业?我已经测试过清空context.User
,但它目前不起作用。
次要:在使用localDbContext
时if(if (true || ...)
(短路的情况下,表示该对象已处理。那么我的错误在哪里呢?
我可以帮你解决这个小问题。不为每个请求调用Configure
方法。行:var localDbContext = services.GetService<CollegeLocalDbContext>();
将仅在第一次执行。在第二个请求中,只会触发匿名方法async (context, next)
,当然现在您将不设置任何localDbContext
。