在 Azure Application Insights 中记录用户身份信息

2021-08-23 16:16:37 浏览数 (1)

导语

Azure Application Insights 是一个非常强大的 APM 工具,用于监视 Web 应用程序。但是,并非我们需要的所有功能都是开箱即用的。例如,为了记录请求和响应正文,我们必须写一个自定义 ASP.NET Core 中间件,就像这篇文章说的那样。

我现在有一个使用 JWT 身份验证的 ASP.NET Core Web API 应用程序。当请求失败时,我想记录用户的身份以便调试。让我们看看如何操作吧~

https://www.azureblue.io/how-to-log-http-request-body-with-asp-net-core-application-insights/

扩展原版 Middleware

我需要修改来自 https://www.azureblue.io/how-to-log-http-request-body-with-asp-net-core-application-insights 的 ASP.NET Core Middleware。

原始代码将请求正文作为自定义属性(Custom Property)记录到 Azure Application Insights。

public class RequestBodyLoggingMiddleware : IMiddleware

{

public async Task InvokeAsync(HttpContext context, RequestDelegate next)

{

var method = context.Request.Method;

context.Request.EnableBuffering();

if (context.Request.Body.CanRead && (method == HttpMethods.Post || method == HttpMethods.Put))

{

using var reader = new StreamReader(

context.Request.Body,

Encoding.UTF8,

detectEncodingFromByteOrderMarks: false,

bufferSize: 512, leaveOpen: true);

var requestBody = await reader.ReadToEndAsync();

context.Request.Body.Position = 0;

var requestTelemetry = context.Features.Get<RequestTelemetry>();

requestTelemetry?.Properties.Add("RequestBody", requestBody);

}

await next(context);

}

}

我的 JWT 身份验证将用户属性添加到Claim中。

var claims = new List<Claim>

{

new("UserId", user.Id.ToString()),

new(ClaimTypes.Name, user.DisplayName),

new(ClaimTypes.Email, request.Email),

new(ClaimTypes.AuthenticationMethod, "Password"),

new("LastLoginTimeUtc", user.LastLoginTimeUtc.ToString())

};

这些Claim 可以从 HttpContext.User 属性获取。

因此,将用户信息记录到 Application Insights 中非常简单,只需从 Claims 中获取值并将它们序列化为 JSON。

if (context.User.Identity is { IsAuthenticated: true })

{

var userId = Guid.Parse(context.User.FindFirst(p => p.Type == "UserId")?.Value ?? string.Empty);

var userName = context.User.Identity?.Name;

var email = context.User.FindFirst(p => p.Type == ClaimTypes.Email)?.Value;

requestTelemetry?.Properties.Add("MpsUser", JsonSerializer.Serialize(new

{

userId,

userName,

email

}, MpsJsonSerializerOptions.Default));

}

最终的代码看起来像这样

public async Task InvokeAsync(HttpContext context, RequestDelegate next)

{

var method = context.Request.Method;

context.Request.EnableBuffering();

if (context.Request.Body.CanRead && (method == HttpMethods.Post || method == HttpMethods.Put))

{

using var reader = new StreamReader(

context.Request.Body,

Encoding.UTF8,

detectEncodingFromByteOrderMarks: false,

bufferSize: 512, leaveOpen: true);

var requestBody = await reader.ReadToEndAsync();

context.Request.Body.Position = 0;

var requestTelemetry = context.Features.Get<RequestTelemetry>();

requestTelemetry?.Properties.Add("RequestBody", requestBody);

if (context.User.Identity is { IsAuthenticated: true })

{

var userId = Guid.Parse(context.User.FindFirst(p => p.Type == "UserId")?.Value ?? string.Empty);

var userName = context.User.Identity?.Name;

var email = context.User.FindFirst(p => p.Type == ClaimTypes.Email)?.Value;

requestTelemetry?.Properties.Add("MpsUser", JsonSerializer.Serialize(new

{

userId,

userName,

email

}, MpsJsonSerializerOptions.Default));

}

}

await next(context);

}

还有一个地方我们需要注意。因为中间件需要获取用户信息,所以必须放在认证授权中间件之后。

app.UseAuthentication();

app.UseAuthorization();

app.UseRequestBodyLogging();

app.UseResponseBodyLogging();

有了这些,我们现在可以看到用户身份被记录到 Azure Application Insights 上。

0 人点赞