我有一个基本的 CRUD Web 应用程序,它将用户表单输入保存到数据库中。当前用户 ID 与表单输入一起保存,在本地和 IIS 上都没有任何问题。但是,当我将网站发布到 IIS 后通过 Serilog 将
EnvironmentUserName
保存在日志中时,EnvironmentUserName
始终保存为“IIS APPPOOL\DefaultAppPool”。当我在本地运行 Web 应用程序时,它会按预期捕获我的用户 ID。
我尝试编写一个自定义丰富器,以使用与检索用户 ID 并使用数据库中的表单输入保存时相同的捕获用户 ID 的逻辑,但结果与
EnvironmentUserName
相同。
我一直在阅读ASP NET Core 应用程序中的模拟,但没有找到可以将其应用于一般日志记录的示例。
当从 IIS 运行 Web 应用程序而不获取“IIS APPOOL\DefaultAppPool”时,如何在日志中包含当前登录用户的 ID?
定制丰富器:
public class CurrentUserEnricher : ILogEventEnricher
{
static readonly string _currentUser;
/// <summary>
/// static constructor to load the environment variable
/// </summary>
static CurrentUserEnricher()
{
_currentUser = WindowsIdentity.GetCurrent().Name.ToUpper();
}
public void Enrich(
LogEvent logEvent,
ILogEventPropertyFactory propertyFactory)
{
var enrichProperty = propertyFactory
.CreateProperty(
"CurrentUser",
_currentUser);
logEvent.AddOrUpdateProperty(enrichProperty);
}
}
这是我的appSettings.config。请注意,在编写自定义丰富器后,我将“CurrentUser”保存为“EnvironmentUserName”。
{
"AllowedHosts": "*",
"ConnectionStrings": {
"DuckDatabase": "data source=*****;initial catalog=*****;integrated security=True;TrustServerCertificate=True",
"GooseDatabase": "data source=*****;initial catalog=*****;integrated security=True;TrustServerCertificate=True"
},
"Serilog": {
"Using": [ "Serilog.Sinks.MSSqlServer", "CustomSerilogEnrichers" ],
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft.AspNetCore": "Warning"
}
},
"WriteTo": [
{
"Name": "MSSqlServer",
"Args": {
"connectionString": "ConsultsDatabase",
"sinkOptionsSection": {
"tableName": "Logs",
"schemaName": "dbo",
"autoCreateSqlTable": false,
"batchPostingLimit": 1000,
"period": "0.00:00:30"
},
"restrictedToMinimumLevel": "Debug",
"columnOptionsSection": {
"addStandardColumns": [ "LogEvent" ],
"removeStandardColumns": [ "MessageTemplate", "Properties" ],
"additionalColumns": [
{
"ColumnName": "EnvironmentUserName",
"PropertyName": "CurrentUser",
"DataType": "varchar",
"AllowNull": true,
"DataLength": 50
},
{
"ColumnName": "MachineName",
"DataType": "varchar",
"AllowNull": true,
"DataLength": 50
},
{
"ColumnName": "Application",
"DataType": "varchar",
"AllowNull": true,
"DataLength": 50
}
]
}
}
}
],
"Enrich": [ "WithMachineName", "WithCurrentUser" ],
"Properties": {
"Application": "Medical Consults"
}
}
}
Program.cs,我在其中设置 Serilog:
using Microsoft.AspNetCore.Authentication.Negotiate;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Server.IIS;
using Serilog;
using System.Security.Principal;
using System.Text;
using System;
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", true)
.Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
try
{
Log.Information("Starting Medical Consults web application");
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog();
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();
// Add services to the container.
builder.Services.AddControllersWithViews()
.AddMvcOptions(options => options.Filters.Add(new AuthorizeFilter("AllowedRoles")));
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("AllowedRoles",
policy => policy.RequireRole("*****"));
});
var app = builder.Build();
app.UseSerilogRequestLogging();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Application terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}
项目规格:
Nuget 包:
我只有两个获取当前登录用户的示例。我确信还有其他一些方法依赖于框架。
Blazor 服务器:使用 AuthenticationStateProvider 类。
AuthenticationState authState = await _authState.GetAuthenticationStateAsync();
ClaimsPrincipal? user = authState.User;
if(user == null)
{
return false;
}
if(user.Identity == null)
{
return false;
}
foreach(var role in roles)
{
if(user.IsInRole(role))
{
return true;
}
}
return false;
使用控制器:
var sv = HttpContext.Features.Get<IServerVariablesFeature>();
var user = (sv == null) ? "No IIS?" : sv["LOGON_USER"];
这些可能不完全是您正在寻找的,并且您可能想要添加/删除更多类型的检查,但这两者都会通过 IIS 生成当前登录的用户。