在a中。Net6Webneneneba API使用NLog,我如何拦截发布的主体,以便在日志记录之前对其进行操作?
以下是我得到的:
我有一个。Net Framework 4.7.2 Web API,带有DelegatingHandler
以拦截请求的主体。然后,我遍历每个键,如果该键在字符串列表中,则替换该值。例如:如果密钥是Password
或Pwd
,我会将该值替换为xxx
,这样我就可以在没有安全问题的情况下记录全文。效果很好。我正试图在上复制这个。Net 6 Web API项目。
以下是我所做的:
我已经查看了NLog源代码,看看它们是如何获得aspnet-request-posted-body
的。我相信我得到了一些东西,但我没有看到NLog调用/使用我的RenderLayout
。
[LayoutRenderer("aspnet-request-posted-body-2")]
public class TestRender : AspNetLayoutRendererBase {
protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent) {
var items = HttpContextAccessor.HttpContext?.Items;
if (items == null || items.Count == 0) {
return;
}
if (items.TryGetValue("aspnet-request-posted-body-2", out var value)) {
builder.Append(value as string);
}
}
}
我的Middleware
public class RequestLoggerMiddleware {
private readonly RequestDelegate _next;
private readonly ILogger<RequestLoggerMiddleware> _logger;
public RequestLoggerMiddleware(RequestDelegate next, ILogger<RequestLoggerMiddleware> logger) {
_next = next;
_logger = logger;
}
public async Task Invoke(HttpContext context) {
var requestBody = await new HttpContextExtensions().PeekBodyAsync(context);
var contentType = context.Request.ContentType;
// Not done yet, but adding this for testing
switch (contentType) {
case "application/x-www-form-urlencoded":
// Clean data
...
// Add to context
context.Items.Add("aspnet-request-posted-body-2", requestBody);
break;
case "application/*+json":
case "application/json":
case "text/json":
// Clean data
...
// Add to context
context.Items.Add("aspnet-request-posted-body-2", JsonSerializer.Serialize(requestBody));
break;
default:
break;
}
_logger
.LogInformation("TESTING");
// With a breakpoint I checked that `content` does have the item listed above
await _next.Invoke(context);
}
}
这是我的Program.cs
文件
var logger = LogManager
.LoadConfiguration(string.Concat(Directory.GetCurrentDirectory(), "/Configs/NLog/nlog.config"))
.Setup()
.SetupExtensions(x => {
x.RegisterLayoutRenderer<TestRender>("aspnet-request-posted-body-2");
})
.GetCurrentClassLogger();
logger.Debug("init main");
try {
var builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders();
builder.Host.UseNLog();
var app = builder.Build();
// Register NLog's Request Body Layout
app.UseMiddleware<NLogRequestPostedBodyMiddleware>();
// Register my custom layout
app.UseMiddleware<RequestLoggerMiddleware>();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
} catch (Exception exception) {
logger.Error(exception, "Stopped program because of exception");
throw;
} finally {
LogManager.Shutdown();
}
当您将请求体存储在HttpContext.Items
-字典中时,就不需要注册自定义布局。只需在NLog.config
中使用${aspnet-item:aspnet-request-posted-body-2}
即可。另请参阅:https://github.com/NLog/NLog/wiki/AspNet-HttpContext-Item-Layout-Renderer
也许可以考虑删除NLogRequestPostedBodyMiddleware
,因为您已经有了自己的RequestLoggerMiddleware
。
Btw。请确保在加载依赖于这些扩展的日志记录配置之前连接SetupExtensions
。示例LogManager.Setup().SetupExtensions(...).LoadConfigurationFromFile(string.Concat(Directory.GetCurrentDirectory(), "/Configs/NLog/nlog.config")