无法访问HttpContext时,如何填充Audit日志的UserId字段?
如何在Audit.NET的EntityFramework审计中获取当前用户ID
这个问题的核心在于Startup配置阶段没有请求上下文,但我们可以借助Audit.WebApi的请求级回调机制,把用户ID传递到后续的EntityFramework审计逻辑里。下面是具体的实现方案:
步骤1:配置Audit.WebApi捕获用户ID
在添加AuditApiAttribute过滤器时,利用OnScopeCreated回调——这个回调会在每个请求的审计Scope创建时触发,此时我们可以访问当前请求的HttpContext来获取用户信息,并将其存入Audit事件的自定义字段中:
GlobalConfiguration.Configuration.Filters.Add(new AuditApiAttribute { OnScopeCreated = scope => { // 获取当前用户ID,兼容匿名请求 string userId = null; var currentContext = HttpContext.Current; if (currentContext?.User?.Identity?.IsAuthenticated == true) { // 如果使用ASP.NET Identity,直接用GetUserId()扩展方法 // userId = currentContext.User.Identity.GetUserId(); // 更通用的方式:从Claims中获取(比如JWT、自定义授权场景) userId = currentContext.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value; } // 将用户ID存入Audit事件的自定义字典 scope.Event.Custom["UserId"] = userId; } });
步骤2:在EntityFramework审计逻辑中提取用户ID
回到ConfigureAudit方法的AuditEntityAction里,我们可以从Audit事件的Custom字段中取出之前存储的用户ID,赋值给AuditLog的UserId属性:
private void ConfigureAudit() { Audit.Core.Configuration.Setup() .UseEntityFramework(x => x .AuditTypeMapper(t => typeof(AuditLog)) .AuditEntityAction<AuditLog>((ev, entry, entity) => { // 从自定义字段中获取用户ID,匿名则为null entity.UserId = ev.Custom.TryGetValue("UserId", out var userId) ? userId as string : null; // 其他审计字段的赋值逻辑... entity.EventDate = DateTime.UtcNow; entity.TableName = entry.Table; // ... }) .IgnoreMatchedProperties() ); }
为什么这个方案可行?
OnScopeCreated是请求级别的回调,只有当实际处理WebApi请求时才会执行,此时HttpContext.Current已经存在,能拿到当前请求的用户身份。- Audit.NET的
AuditEvent对象会贯穿整个审计流程,我们在WebApi阶段存入的自定义信息,会被带到EntityFramework的审计动作中,完美解决了上下文传递的问题。
内容的提问来源于stack exchange,提问作者JH-Sen-Ren
相关产品推荐
相关产品推荐

