当我无权访问HttpContext时,如何填充我的审核日志UserId字段?

时间:2019-09-19 10:48:19

标签: c# entity-framework audit.net

我有一个包含两个项目的解决方案,我的API层和我的数据层。

数据层使用的是Entity Framework,并且不了解ASP.NET WebApi。

API层正在使用ASP.NET WebApi。

我计划使用Audit.NET审核记录更改。

当前,我已经在我的API项目中安装了Audit.NET,Audit.EntityFramework和Audit.WebApi。

我希望使用审核过滤器属性。 (config.Filters.Add(new AuditApiAttribute());

我的问题是,当我要填充EntityLog对象时,我也想用当前正在执行授权操作的用户的ID填充UserId字段;如果该操作是匿名的,则为null。

作为Startup.cs的一部分,我运行此功能来配置Audit.NET:

private void ConfigureAudit()
        {
            Audit.Core.Configuration.Setup()
                .UseEntityFramework(x => x
                    .AuditTypeMapper(t => typeof(AuditLog))
                    .AuditEntityAction<AuditLog>((ev, entry, entity) =>
                    {
                        entity.UserId = ???;
                        // other fields...
                    })
                    .IgnoreMatchedProperties()
                );
        }

很明显,此时我不能使用HttpContext.Current.User.Identity.GetUserId(),因为我不在控制器内部,而且我看不到将UserId传递给Audit事件的方法。

此时我如何检索UserId?

3 个答案:

答案 0 :(得分:1)

一些用于ASP.NET Core的东西...

鉴于ASP.NET Core已删除HttpContext.Current以支持基于DI的访问,我想在@ thepirat000的答案中添加一些更新,以反映访问{{1}的一种可能方式}在控制器外部。

  1. HttpContext中的ConfigureServices方法中,注册依赖项:

    Startup.cs
  2. 在方法services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); 中的Configure中为注册的依赖项添加参数注入,使用它来获取上下文并使用它来设置自定义字段。

    Startup.cs
  3. 照常访问自定义字段:

     public void Configure(/* your existing parameters... */, IHttpContextAccessor httpContextAccessor)
     {
          ...
    
         Audit.Core.Configuration.AddCustomAction(ActionType.OnScopeCreated, scope =>
         {
            scope.SetCustomField("User", httpContextAccessor.HttpContext.User.Identity.Name);
         });
     }
    

答案 1 :(得分:0)

我使用的方法是IUserContextLocator接口,该接口成为对DbContext或任何实现审核的类的依赖。该接口的实现在Web应用程序中创建,并通过依赖项注入进行连接,以使用构造函数初始化来提供当前会话的详细信息。这样DbContext或其他审核服务可以从IUserContextLocator中的方法解析当前用户结构,该方法又从会话中获取。

我当前的实现正在工作中,因此我没有一个方便的示例,但是明天我可以添加它的胆量。在这里可以看到类似的原理:http://josephwoodward.co.uk/2014/06/sessions-asp-net-mvc-using-dependency-injection/

本质上,域级代码无法访问HttpContext.Current之类的东西,但是在Web应用程序中初始化的实现可以。通过域可以引用的公共接口在您的DI中注册该实现,可以注入Web应用程序提供的依赖项,从而允许您访问会话数据。此示例将其称为注册表,这可能是一种更准确的模式。

答案 2 :(得分:0)

除了史蒂夫(Steve)的答案,我想您应该还可以从Custom Field中添加一个OnScopeCreated custom action,就像在asp.net启动逻辑上一样:

Audit.Core.Configuration.AddCustomAction(ActionType.OnScopeCreated, scope =>
{
    scope.SetCustomField("User", HttpContext.Current.User.Identity.GetUserId());
});

因此,您将在EF数据提供者的AuditEvent上具有该字段,并且应该能够像这样进行检索:

Audit.Core.Configuration.Setup()
    .UseEntityFramework(_ => _
        .AuditTypeMapper(t => typeof(AuditLog))
        .AuditEntityAction<AuditLog>((ev, entry, entity) =>
        {
            var x = ev.CustomFields["User"];
            ...
        })
        .IgnoreMatchedProperties());
  

注意:如果您仅对审核实体框架数据库上下文感兴趣,则不需要Audit.WebApi库。那是为了审计控制器的动作。