ASP.NET Core 6.0中DeleteAsync操作日志不合规的问题处理咨询
现有应用环境与配置
我维护的是一个基于ASP.NET Core 6.0的WebAPI项目,使用Entity Framework Core和Serilog做日志记录。
Serilog注册代码(Program.cs)
var logger = new LoggerConfiguration() .MinimumLevel.Override("Microsoft", LogEventLevel.Information) .Enrich.FromLogContext() .Enrich.WithMachineName() .Enrich.WithProperty("Assembly", typeof(Program).Assembly.GetName().Name) .WriteTo.Console() .CreateLogger(); builder.Logging.ClearProviders(); builder.Logging.AddSerilog(logger);
配置文件(appsettings.json)中的Serilog配置
"Serilog": { "Using": [], "MinimumLevel": { "Default": "Information", "Override": { "Microsoft": "Debug", "System": "Debug" } }, "WriteTo": [ { "Name": "Async", "Args": { "configure": [ { "Name": "Console", "Args": { "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" } } ] } } ], "Properties": { "ApplicationName": "EFCoreRelationshipsTutorial" } }
当前日志输出
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/1.1 DELETE http://localhost:35847/Education/a65f7f0c-2a29-4da0-bd4b-d737320730c6 - - Microsoft.AspNetCore.Cors.Infrastructure.CorsService: Information: CORS policy execution successful. Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executing endpoint 'DemoApplication.Api.Controllers.EducationController.DeleteAsync (DemoApplication.Api)' Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Information: Route matched with {action = "Delete", controller = "Education"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] DeleteAsync(System.Guid) on controller DemoApplication.Api.Controllers.EducationController (DemoApplication.Api). Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Information: Executing action method DemoApplication.Api.Controllers.EducationController.DeleteAsync (DemoApplication.Api) - Validation state: Valid DemoApplication.Application.Behaviors.LoggingBehavior: Information: ----- Handling command DeleteEducationCommand (DemoApplication.Application.Feature.Educations.Commands.DeleteEducation.DeleteEducationCommand) DemoApplication.Application.Behaviors.ValidatorBehavior: Information: ----- Validating command DeleteEducationCommand Microsoft.EntityFrameworkCore.Infrastructure: Information: Entity Framework Core 6.0.7 initialized 'TrackManagementContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL:6.0.6+6fa8f3c27a7c241a66e72a6c09e0b252509215d0' with options: NoTracking Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Information: Executed action DemoApplication.Api.Controllers.EducationController.DeleteAsync (DemoApplication.Api) in 496.7454ms Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executed endpoint 'DemoApplication.Api.Controllers.EducationController.DeleteAsync (DemoApplication.Api)' Exception thrown: 'DemoApplication.Application.Exceptions.NotFoundException' in System.Private.CoreLib.dll Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request finished HTTP/1.1 DELETE http://localhost:35847/Education/a65f7f0c-2a29-4da0-bd4b-d737320730c6 - - - 404 - application/json 4634.2334ms
Checkmarx安全告警
The sensitive operation DeleteAsync is not properly logged and, therefore, important execution details may be omitted.
(中文翻译:敏感操作DeleteAsync未被正确记录,可能遗漏重要执行细节)
相关业务代码
控制器DeleteAsync方法
public async Task<IActionResult> DeleteAsync(Guid id) { await this.mediator.Send(new DeleteProductCommand { Id = id }).ConfigureAwait(false); return this.NoContent(); }
命令处理逻辑
public async Task<Unit> Handle(DeleteProductCommand request, CancellationToken cancellationToken) { ... await this.productRepository.DeleteAsync(productToDelete).ConfigureAwait(false); ... }
处理方案:无需请求安全团队忽略告警,应用层面可修复
Checkmarx的告警是合理的——当前日志只记录了请求流程和命令处理的框架级日志,缺少删除操作的核心业务上下文(比如具体删除的ID、操作是否成功、异常详情),一旦出现问题根本没法追溯。直接在应用层面修复即可,步骤如下:
1. 给删除操作添加关键业务日志
在命令处理的Handle方法里,补充删除前后的日志,把关键信息(比如要删除的ID、操作结果)记录下来,异常场景也要明确日志:
// 记得注入ILogger<DeleteProductCommandHandler> private readonly ILogger<DeleteProductCommandHandler> _logger; public async Task<Unit> Handle(DeleteProductCommand request, CancellationToken cancellationToken) { _logger.Information("发起产品删除请求,产品ID: {ProductId}", request.Id); var productToDelete = await _productRepository.GetByIdAsync(request.Id, cancellationToken); if (productToDelete == null) { _logger.Warning("删除失败:未找到指定产品,产品ID: {ProductId}", request.Id); throw new NotFoundException($"产品 {request.Id} 不存在"); } await _productRepository.DeleteAsync(productToDelete, cancellationToken); _logger.Information("产品删除成功,产品ID: {ProductId}", request.Id); return Unit.Value; }
2. 修复Serilog配置读取问题
当前Program.cs里的Serilog是硬编码配置,完全没用到appsettings里的Serilog设置,导致配置文件里的日志级别、异步输出等配置失效。修改Program.cs的Serilog初始化代码,让它读取配置文件:
var logger = new LoggerConfiguration() .ReadFrom.Configuration(builder.Configuration) // 新增:读取配置文件中的Serilog配置 .Enrich.FromLogContext() .Enrich.WithMachineName() .Enrich.WithProperty("Assembly", typeof(Program).Assembly.GetName().Name) .CreateLogger(); builder.Logging.ClearProviders(); builder.Logging.AddSerilog(logger);
3. 确保异常日志被完整记录
当前日志里只显示了Exception thrown的提示,没有详细的异常堆栈和上下文。可以在LoggingBehavior中捕获命令处理的异常,记录完整的错误日志:
public class LoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> { private readonly ILogger<LoggingBehavior<TRequest, TResponse>> _logger; public LoggingBehavior(ILogger<LoggingBehavior<TRequest, TResponse>> logger) { _logger = logger; } public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken) { _logger.Information("----- Handling command {CommandName} ({@Command})", typeof(TRequest).Name, request); try { var response = await next(); _logger.Information("----- Command {CommandName} handled successfully", typeof(TRequest).Name); return response; } catch (Exception ex) { _logger.Error(ex, "----- Command {CommandName} failed", typeof(TRequest).Name); throw; } } }
修复后,日志会包含删除操作的完整上下文,既能满足安全审计要求,也方便后续排查问题,完全不需要忽略告警。
内容的提问来源于stack exchange,提问作者One Developer

