ABP - 审计日志 [AuditedAttribute、IAuditingManager、EntityAuditingHelper]
审计日志
- 核心辅助类:
AuditedAttribute:标记类/方法记录审计日志。IAuditingManager:手动管理审计日志。EntityAuditingHelper:实体审计辅助(自动填充创建/修改时间)。
审计日志(Auditing)核心类示例与讲解
ABP的审计日志功能用于自动记录系统中关键操作的细节(如“谁在什么时间操作了什么数据”),核心价值是追溯操作源头、保障数据安全。以下针对AuditedAttribute、IAuditingManager、EntityAuditingHelper三个核心类,结合实际场景讲解用法:
一、AuditedAttribute:自动记录审计日志(声明式用法)
AuditedAttribute是最常用的审计工具,通过标记类或方法,让框架自动记录操作日志,无需手动编写日志代码。支持类级别(所有方法生效)和方法级别(单个方法生效)。
1. 类级别标记(所有方法自动审计)
using Volo.Abp.Auditing;
using Volo.Abp.Application.Services;
// 标记整个服务类,所有公共方法都会记录审计日志
[Audited]
public class BookAppService : ApplicationService
{
private readonly IRepository<Book, Guid> _bookRepo;
public BookAppService(IRepository<Book, Guid> bookRepo)
{
_bookRepo = bookRepo;
}
// 自动记录:谁(CreatorId)、何时(Time)、调用了此方法、输入参数(id)、返回结果(BookDto)
public async Task<BookDto> GetAsync(Guid id)
{
var book = await _bookRepo.GetAsync(id);
return ObjectMapper.Map<Book, BookDto>(book);
}
// 自动记录:新增操作的输入(CreateBookInput)、新增的书籍ID等
public async Task<BookDto> CreateAsync(CreateBookInput input)
{
var book = ObjectMapper.Map<CreateBookInput, Book>(input);
await _bookRepo.InsertAsync(book);
return ObjectMapper.Map<Book, BookDto>(book);
}
}
2. 方法级别标记(指定方法审计)
public class OrderAppService : ApplicationService
{
// 仅标记此方法,其他方法不审计(适合只需要追溯关键操作的场景)
[Audited]
public async Task<OrderDto> PayAsync(Guid orderId, decimal amount)
{
// 支付业务逻辑...
}
// 不标记,不记录审计日志(如普通查询操作)
public async Task<List<OrderDto>> GetUserOrdersAsync(Guid userId)
{
// 普通查询逻辑...
}
}
讲解
-
自动记录内容:框架会自动捕获「操作人ID、操作时间、方法名、输入参数、返回结果、执行时长」,无需手动传参。
-
排除敏感参数:若方法参数包含密码等敏感信息,可通过
[DisableAuditing]标记参数排除审计:public async Task ResetPasswordAsync( Guid userId, [DisableAuditing] string newPassword // 不记录密码到审计日志 ) { // 重置密码逻辑... } -
适用场景:大多数常规CRUD操作、支付/审批等关键业务操作,用
[Audited]可零代码实现审计追溯。
二、IAuditingManager:手动管理审计日志(编程式用法)
当需要自定义审计内容(如补充业务备注、记录非方法调用的操作)时,可通过IAuditingManager手动创建和提交审计日志,灵活度更高。
示例:手动记录自定义审计日志
using Volo.Abp.Auditing;
using Volo.Abp.DependencyInjection;
public class InventoryService : ITransientDependency
{
private readonly IAuditingManager _auditingManager;
private readonly IRepository<Inventory, Guid> _inventoryRepo;
// 注入IAuditingManager
public InventoryService(IAuditingManager auditingManager, IRepository<Inventory, Guid> inventoryRepo)
{
_auditingManager = auditingManager;
_inventoryRepo = inventoryRepo;
}
public async Task AdjustStockAsync(Guid productId, int adjustCount, string reason)
{
// 1. 开启审计日志(创建审计范围)
using (var auditingScope = _auditingManager.BeginScope())
{
try
{
// 2. 业务逻辑:调整库存
var inventory = await _inventoryRepo.GetAsync(x => x.ProductId == productId);
inventory.Stock += adjustCount;
await _inventoryRepo.UpdateAsync(inventory);
// 3. 自定义审计内容(补充业务信息)
var auditLog = auditingScope.Log;
auditLog.MethodName = "AdjustStockAsync"; // 手动指定方法名
auditLog.Comments = $"库存调整原因:{reason}"; // 补充业务备注
auditLog.ExtraProperties["ProductId"] = productId; // 额外记录产品ID
auditLog.ExtraProperties["BeforeStock"] = inventory.Stock - adjustCount; // 调整前库存
auditLog.ExtraProperties["AfterStock"] = inventory.Stock; // 调整后库存
// 4. 提交审计日志(若不调用,框架会在作用域结束时自动提交)
await auditingManager.SaveAsync(auditLog);
}
catch (Exception ex)
{
// 5. 异常时标记日志状态(可选)
auditingScope.Log.Exception = ex;
throw;
}
}
}
}
讲解
- 核心方法:
BeginScope():创建审计范围,所有在范围内的操作可被记录到同一条日志。SaveAsync(auditLog):手动提交日志(若不调用,框架会在using作用域结束时自动提交)。
- 自定义字段:通过
auditLog.ExtraProperties可添加任意业务相关的额外信息(如库存调整前后的值、操作原因),满足个性化追溯需求。 - 适用场景:非标准方法调用的操作(如定时任务调整数据、批量处理)、需要补充业务备注的关键操作。
三、EntityAuditingHelper:实体审计辅助(自动填充审计字段)
EntityAuditingHelper用于手动触发实体的审计字段填充(如CreationTime、CreatorId、LastModificationTime),通常在“框架自动填充失效”的场景下使用(如手动new的实体、非仓储操作的实体)。
示例:手动填充实体审计字段
using Volo.Abp.Auditing;
using Volo.Abp.Domain.Entities;
using Volo.Abp.DependencyInjection;
public class CustomDataService : ITransientDependency
{
private readonly EntityAuditingHelper _auditingHelper;
private readonly ICurrentUser _currentUser;
private readonly MyCustomDbContext _dbContext; // 自定义数据库上下文
public CustomDataService(
EntityAuditingHelper auditingHelper,
ICurrentUser currentUser,
MyCustomDbContext dbContext)
{
_auditingHelper = auditingHelper;
_currentUser = currentUser;
_dbContext = dbContext;
}
public async Task AddCustomDataAsync(string dataContent)
{
// 1. 手动创建实体(未通过仓储,框架无法自动填充审计字段)
var customData = new CustomData
{
Content = dataContent
// 此时:CreationTime、CreatorId 等审计字段为默认值(如DateTime.MinValue、null)
};
// 2. 手动调用EntityAuditingHelper填充审计字段
_auditingHelper.SetCreationAuditProperties(
entity: customData,
currentUserId: _currentUser.Id // 传递当前用户ID(用于填充CreatorId)
);
// 3. 手动将实体添加到数据库(非仓储操作)
_dbContext.CustomDatas.Add(customData);
await _dbContext.SaveChangesAsync();
// 最终实体的审计字段:
// CreationTime = 当前时间
// CreatorId = 当前用户ID(如Guid.Parse("..."))
}
}
// 定义带审计字段的实体
public class CustomData : Entity<Guid>, IHasCreationTime, IHasCreator
{
public string Content { get; set; }
public DateTime CreationTime { get; set; } // 需手动填充的审计字段
public Guid? CreatorId { get; set; } // 需手动填充的审计字段
}
讲解
- 核心方法:
SetCreationAuditProperties(entity, currentUserId):填充“创建审计”字段(CreationTime、CreatorId)。SetModificationAuditProperties(entity, currentUserId):填充“修改审计”字段(LastModificationTime、LastModifierId)。SetDeletionAuditProperties(entity, currentUserId):填充“删除审计”字段(DeletionTime、DeleterId,适用于软删除)。
- 适用场景:未通过ABP仓储操作的实体(如直接用EF Core的
DbContext)、手动new的实体,需要补充审计字段时使用。 - 自动填充场景:若实体通过
IRepository的InsertAsync/UpdateAsync操作,框架会自动调用EntityAuditingHelper,无需手动处理(如之前的BookAppService示例)。
四、审计日志的核心配置与查看
1. 基础配置(模块中启用审计)
ABP默认启用审计,若需调整配置(如排除某些方法、设置日志保存方式),可在模块的ConfigureServices中配置:
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpAuditingOptions>(options =>
{
// 全局排除审计的方法(如所有以"Internal"开头的方法)
options.IgnoredMethods.Add("Internal*");
// 审计日志保存到数据库(默认),也可配置保存到文件/第三方日志系统
options.IsEnabledForGetRequests = true; // 是否记录GET请求(默认false,避免查询日志过多)
});
}
2. 查看审计日志
审计日志默认保存到AbpAuditLogs表(EF Core),可通过IAuditLogRepository查询历史日志:
public async Task<List<AuditLogDto>> GetAuditLogsAsync(DateTime startDate)
{
var logs = await _auditLogRepo.GetListAsync(
filter: log => log.ExecutionTime >= startDate,
orderBy: log => log.ExecutionTime.Descending()
);
return ObjectMapper.Map<List<AuditLog>, List<AuditLogDto>>(logs);
}
五、总结:三类核心类的适用场景
| 类/特性 | 用法方式 | 核心优势 | 适用场景 |
|---|---|---|---|
AuditedAttribute |
声明式(特性) | 零代码、自动记录 | 常规CRUD、关键方法(如支付、审批) |
IAuditingManager |
编程式(代码) | 灵活自定义、补充业务信息 | 非标准操作、需额外备注的关键业务 |
EntityAuditingHelper |
编程式(代码) | 手动填充审计字段 | 非仓储操作的实体、手动创建的实体 |
通过这三类工具,ABP可覆盖从“自动记录”到“手动定制”的全场景审计需求,确保系统操作可追溯、数据安全有保障。

浙公网安备 33010602011771号