Logging'e Password Yazmak
Body'yi olduğu gibi sink'e bırakmak

Debug için body log'u açtım, kapatmayı unuttum. Login, register, password-reset aynı middleware'den geçti. Şifre hash'lenmeden önce log'a düştü. Retention 30 gün. 30 gün boyunca o alan greplenebilir kaldı.
public sealed class SafeRequestLogging(RequestDelegate next, ILogger log)
{
private static readonly HashSet Drop = new(StringComparer.OrdinalIgnoreCase)
{
"password", "newPassword", "token", "refresh", "authorization"
};
public async Task Invoke(HttpContext ctx)
{
using (log.BeginScope(new Dictionary
{
["requestId"] = ctx.TraceIdentifier,
["path"] = ctx.Request.Path.Value ?? ""
}))
{
if (ctx.Request.ContentType?.Contains("json") == true
&& ctx.Request.ContentLength is > 0 and < 8_000)
{
ctx.Request.EnableBuffering();
using var reader = new StreamReader(ctx.Request.Body, leaveOpen: true);
var raw = await reader.ReadToEndAsync();
ctx.Request.Body.Position = 0;
log.LogInformation("Request body {Body}", Redact(raw));
}
await next(ctx);
}
}
static string Redact(string json)
{
using var doc = JsonDocument.Parse(json);
var buffer = new MemoryStream();
using var writer = new Utf8JsonWriter(buffer);
RedactElement(doc.RootElement, writer);
writer.Flush();
return Encoding.UTF8.GetString(buffer.ToArray());
}
static void RedactElement(JsonElement el, Utf8JsonWriter w)
{
if (el.ValueKind != JsonValueKind.Object)
{
el.WriteTo(w);
return;
}
w.WriteStartObject();
foreach (var p in el.EnumerateObject())
{
if (Drop.Contains(p.Name)) w.WriteString(p.Name, "***");
else { w.WritePropertyName(p.Name); RedactElement(p.Value, w); }
}
w.WriteEndObject();
}
}
Authorization header zaten default log'da olmamalı. Token query string'de ise path'i de kırp. Emre'nin Serilog yazısı correlation id ister; ben password'un o id'nin yanında durmamasını isterim. Body log'u varsayılan kapalı. Açınca redact açılır, tersi değil.
Yorumlar
Yorumlar (0)
Yorumlar üyelere açık. Üye ol · Giriş yap