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.
}
在我目前工作的项目中,我需要审核对许多数据库表的更改。为此,我正在考虑使用 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.
}