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

时间:2019-06-27 23:42:48

标签: entity-framework asp.net-core jwt entity-framework-plus

在我目前从事的项目中,我需要审核对许多数据库表的更改。为此,我正在考虑使用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; dr; 当我使用JWT令牌时如何在IdentityDbContext中获取当前的用户名?

2 个答案:

答案 0 :(得分: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.
}

答案 1 :(得分:-1)

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

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