AspNetCore 2.1 IdentityDbContext:如何获取当前用户名

AspNetCore 2.1 IdentityDbContext: How to get current username

在我目前工作的项目中,我需要审核对许多数据库表的更改。为此,我正在考虑使用 nuget Z.EntityFramework.Plus.Audit.EFCore。我一直在试验,它似乎最能满足我的需求。我一直在关注文档 here

可以像这样在我的控制器中保存审计条目:

public myFunction(){
   //... 
   var audit = new Audit();
   _context.SaveChanges(audit); 
}

但如果我这样做,就违反了DRY原则。有一种方法可以覆盖 SaveChanges() 和 SaveChagesAsync() 函数,而且效果非常好。这样的事情是这样完成的:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
        {
            AuditManager.DefaultConfiguration.AutoSavePreAction = (context, audit) =>
               // ADD "Where(x => x.AuditEntryID == 0)" to allow multiple SaveChanges with same Audit
               (context as ApplicationDbContext).AuditEntries.AddRange(audit.Entries);
        }


        public override int SaveChanges()
        {
            var audit = new Audit { }; //Problem would be here
            audit.PreSaveChanges(this);
            var rowAffecteds = base.SaveChanges();
            audit.PostSaveChanges();

            if (audit.Configuration.AutoSavePreAction != null)
            {
                audit.Configuration.AutoSavePreAction(this, audit);
                base.SaveChanges();
            }

            return rowAffecteds;
        }

        public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
        {
            var audit = new Audit { }; //Problem would be here
            audit.PreSaveChanges(this);
            var rowAffecteds = await base.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
            audit.PostSaveChanges();

            if (audit.Configuration.AutoSavePreAction != null)
            {
                audit.Configuration.AutoSavePreAction(this, audit);
                await base.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
            }

            return rowAffecteds;
        }

//... DbContext Code
        }

现在这是一个更好的选择,非常干燥且更易于维护。问题是,如何获取当前用户名以便我可以执行类似

的操作
var audit = new Audit { CreatedBy = "my_current_username"};

在控制器中可以使用指令

var username = this.User.Identity.Name;

但这在 IdentityDbContext 中不可用。我确实尝试注入 UserManager,但它没有可用的功能。

tl;博士; 当我使用 JWT 令牌时,如何在 IdentityDbContext 中获取当前用户名?

您可以注入 IHTTPContextAccessor 服务,然后使用它来获取当前用户名。但是,此服务不是线程安全的 此外,这意味着您不能在 Web 应用程序 AFAIK 的范围之外使用 DBContext。

更多信息在这里:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-2.2

ConfigureServices中:

services.AddHttpContextAccessor();

services.AddDbContext<FooContext>((provider, options) =>
    options.UseSqlServer(Configuration.GetConnectionString("Foo"))
           .UseInternalServiceProvider(provider);

FooContext.SaveChanges/FooContext.SaveChangesAsync:

var httpContextAccessor = this.GetService<IHttpContextAccesor>();
var userName = httpContextAccessor.HttpContext?.User.Identity.Name;
if (userName != null)
{
    // You've got the username. Do something with it.
}