概述
审计日志(Auditing)用于记录用户在系统中的操作行为,是企业级应用中常见的合规需求。silky 框架通过 Silky.Http.Auditing 模块提供审计能力,能够自动记录每次 HTTP 请求的关键信息(请求者、时间、结果、耗时等),并通过 RPC 调用链将各微服务的操作动作聚合到同一条审计日志中。
审计信息采集流程
HTTP 请求到达网关
↓
AuditingMiddleware(记录 HTTP 层信息)
↓
RPC 调用目标微服务
↓
AuditingServerFilter(各微服务记录服务条目执行动作)
↓
通过 RpcContext 将动作信息传回网关
↓
聚合为完整 AuditLogInfo → 调用 IAuditingStore.SaveAsync()
审计日志结构
AuditLogInfo 包含以下关键信息:
| 属性 | 类型 | 说明 |
|---|---|---|
UserId | object? | 当前登录用户 ID(来自 Session) |
UserName | string | 当前登录用户名 |
TenantId | object? | 当前租户 ID(多租户场景) |
Url | string | 请求路径 |
HttpMethod | string | HTTP 请求方法 |
ClientIpAddress | string | 客户端 IP 地址 |
ClientId | string | 连接 ID(HttpContext.Connection.Id) |
BrowserInfo | string | User-Agent 信息 |
CorrelationId | string | 请求关联 ID(TraceIdentifier) |
ExecutionTime | DateTimeOffset | 请求开始时间 |
ExecutionDuration | int | 请求总耗时(毫秒) |
HttpStatusCode | int? | HTTP 响应状态码 |
RequestParameters | string | 请求参数(JSON) |
ExceptionMessage | string | 异常信息(如有) |
Actions | List<AuditLogActionInfo> | 各微服务服务条目的执行动作明细 |
每个 AuditLogActionInfo 代表一个 RPC 服务条目的执行动作,包含服务方法名、参数、耗时、异常等。
如何使用
步骤一:在网关中启用审计中间件
在网关的 Startup.cs 中启用 UseAuditing():
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseSilkyIdentity();
app.UseAuditing(); // 启用审计中间件(建议放在认证之后)
app.UseEndpoints(endpoints =>
{
endpoints.MapSilkyRpcServices();
});
}
步骤二:实现 IAuditingStore 接口
审计日志的持久化由开发者自己实现,通过实现 IAuditingStore 接口将日志写入数据库或其他存储:
using Silky.Http.Auditing;
using Silky.Rpc.Auditing;
public class DatabaseAuditingStore : IAuditingStore, IScopedDependency
{
private readonly IAuditLogRepository _auditLogRepository;
public DatabaseAuditingStore(IAuditLogRepository auditLogRepository)
{
_auditLogRepository = auditLogRepository;
}
public async Task SaveAsync(AuditLogInfo auditLogInfo)
{
var auditLog = new AuditLog
{
UserId = auditLogInfo.UserId?.ToString(),
UserName = auditLogInfo.UserName,
Url = auditLogInfo.Url,
HttpMethod = auditLogInfo.HttpMethod,
ClientIpAddress = auditLogInfo.ClientIpAddress,
ExecutionTime = auditLogInfo.ExecutionTime,
ExecutionDuration = auditLogInfo.ExecutionDuration,
HttpStatusCode = auditLogInfo.HttpStatusCode,
ExceptionMessage = auditLogInfo.ExceptionMessage,
};
await _auditLogRepository.InsertAsync(auditLog);
}
}
步骤三:注册 IAuditingStore 实现
在 Startup.cs 的 ConfigureServices 中注册:
public void ConfigureServices(IServiceCollection services)
{
services.AddSilkyHttpCore()
.AddAuditing<DatabaseAuditingStore>(); // 注册审计存储实现
}
提示
如果不注册 IAuditingStore,审计中间件仍然会正常运行,但只会将审计信息以 Debug 级别输出到日志,不会持久化存储。这在开发阶段非常便于调试。
审计配置
通过 Auditing 配置节点控制审计行为:
auditing:
isEnabled: true # 是否启用审计(默认 true)
isEnabledForAnonymousUsers: true # 是否对匿名用户也记录审计(默认 true)
isEnabledForGetRequests: false # 是否对 GET 请求记录审计(默认 false,通常只审计写操作)
hideErrors: true # 是否在审计日志中隐藏详细错误堆栈(默认 true)
alwaysLogOnException: true # 发生异常时是否强制记录审计(默认 true)
说明
isEnabled 控制全局开关。当 isEnabled: false 时,审计中间件对所有请求直接跳过,不产生任何开销。
禁用特定接口的审计
对于不需要审计的接口(如内部调用接口、高频查询接口),可以使用 [DisableAuditing] 特性:
[ServiceRoute]
public interface IOrderAppService
{
// 默认启用审计
[HttpPost]
Task<OrderOutput> CreateOrderAsync(CreateOrderInput input);
// 禁用该方法的审计
[HttpGet("{id:long}")]
[DisableAuditing]
Task<OrderOutput> GetAsync(long id);
}
[DisableAuditing] 也可以应用在接口类型级别,禁用整个服务的审计:
[ServiceRoute]
[DisableAuditing] // 整个服务不记录审计
public interface IInternalSyncAppService
{
Task SyncAsync(SyncInput input);
}
[DisableAuditing] 还可以应用在 DTO 属性级别,防止敏感字段被记录到审计日志的请求参数中:
public class CreateUserInput
{
public string UserName { get; set; }
[DisableAuditing] // 密码字段不记录到审计日志
public string Password { get; set; }
}
