2016-10-06 8 views
5

Я пытаюсь использовать Serilog вместе с моим проектом ASP.Net Core 1.0. Я просто не могу заставить текущего пользователя войти в список зарегистрированных пользователей.Добавить пользователя в контекст журнала при использовании Serilog и Asp.Net Core

Кто-нибудь еще это понял?

Я попытался это:

using System.Threading.Tasks; 
using Serilog.Context; 
using Microsoft.AspNetCore.Builder; 
using Microsoft.AspNetCore.Http; 
using System.Security.Claims; 
using xxx.Models; 

namespace xxx.Utils 
{ 
    public class EnrichSerilogContextMiddleware 
    { 
     private readonly RequestDelegate _next; 
     public EnrichSerilogContextMiddleware(RequestDelegate next) 
     { 
      _next = next; 
     } 

     public async Task Invoke(HttpContext httpContext) 
     { 

      var username = httpContext.User.Identity.Name; 
      if (httpContext.User.Identity.IsAuthenticated) 
      { 
       var userFullName = (((ClaimsIdentity)httpContext.User.Identity).FindFirst(Member.FullnameClaimName).Value); 
       var userName = "[email protected]"; 
       LoggerEnricher.AddEntryPointContext(userFullName, userName); 
      } 
      else 
      { 
       LoggerEnricher.AddEntryPointContext(); 
      } 


      await _next(httpContext); 
     } 
    } 

    public static class LoggerEnricher 

    { 
     public static void AddEntryPointContext(string userFullName = null, string username = null) 
     { 
      if (!string.IsNullOrWhiteSpace(username) || !string.IsNullOrWhiteSpace(userFullName)) 
      { 
       LogContext.PushProperty("Username", username); 
       LogContext.PushProperty("UserFullename", userFullName); 
      } 
      else 
      { 
       LogContext.PushProperty("Username", "Anonymous"); 
      } 

     } 

     public static void EnrichLogger(this IApplicationBuilder app) 
     { 
      app.UseMiddleware<EnrichSerilogContextMiddleware>(); 
     } 
    } 
} 

Я запускать это в Startup.cs, добавив:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
    { 
     loggerFactory.AddConsole(Configuration.GetSection("Logging")); 
     loggerFactory.AddDebug(); 
     loggerFactory.AddSerilog(); 
     app.EnrichLogger(); 
     ... 
    } 

Но это всегда заканчивается с "Anonymous" в качестве имени пользователя.

Заранее спасибо

Сорен Rokkedal

+0

Вы пробовали Добавляя это в трубопровод после аутентификации? – Brad

+0

Не уверен, что вы имеете в виду с этим –

+0

Я имею в виду вызов 'app.EnrichLogger();' после вызова 'app.UseAuthentication (....);' или любого другого метода проверки подлинности. Вы вводите логгер слишком рано в конвейере, прежде чем пользователь будет аутентифицирован, поэтому он всегда будет анонимным. – Brad

ответ

2

Вам нужно вызвать _next в блоке, как так:

public async Task Invoke(HttpContext httpContext) 
    { 

     var username = httpContext.User.Identity.Name; 
     if (httpContext.User.Identity.IsAuthenticated) 
     { 
      var userFullName = (((ClaimsIdentity)httpContext.User.Identity).FindFirst(Member.FullnameClaimName).Value); 
      var userName = "[email protected]"; 

      using (LogContext.PushProperty("Username", userName) 
      using (LogContext.PushProperty("UserFullName", userFullName) 
      { 
       await _next(httpContext); 
      } 
     } 
     else 
     { 
      await _next(httpContext); 
     } 
    } 
+0

Спасибо за ответ. Я считаю, что оригинальная публикация включала в себя ожидание _next (httpContext). Реализация предлагаемого решения не помогла. Каждый раз, когда вызывается метод Invoke, httpContext.User.Identity.IsAuthenticated является ложным. Любые идеи? –

+0

Спасибо за последующее наблюдение. Тогда не уверен в этом. У вас есть 'Enrich.FromLogContext()' установленный на 'LoggerConfiguration'? –

+0

Да, я настроил это –

4

Я был в состоянии получить аутентификацией пользователя Active Directory с помощью всего нескольких строк кода. Я не очень разбираюсь в проверке подлинности с использованием Core, в частности, о требованиях, но, возможно, это приведет вас к вам или, как минимум, поможет другим, которые приходят вместе с подобной проблемой, но с AD.

Ключевые линии Enrich.FromLogContext() и app.Use(async...

public class Startup 
{ 
    public IConfigurationRoot Configuration { get; } 

    public Startup(IHostingEnvironment env) 
    { 
     Log.Logger = new LoggerConfiguration() 
        .Enrich.FromLogContext() // Populates a 'User' property on every log entry 
        .WriteTo.MSSqlServer(Configuration.GetConnectionString("MyDatabase"), "Logs") 
        .CreateLogger(); 
    } 

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
    { 
     loggerFactory.WithFilter(new FilterLoggerSettings 
           { 
            { "Default", LogLevel.Information }, 
            { "Microsoft", LogLevel.Warning }, 
            { "System", LogLevel.Warning } 
           }) 
        .AddSerilog(); 

     app.Use(async (httpContext, next) => 
       { 
        var userName = httpContext.User.Identity.IsAuthenticated ? httpContext.User.Identity.Name : "unknown"; 
        LogContext.PushProperty("User", !String.IsNullOrWhiteSpace(userName) ? userName : "unknown"); 
        await next.Invoke(); 
       }); 
    } 
} 

Для проверки подлинности AD через IIS/Kestrel web.config, требуется настройка forwardWindowsAuthToken следующим образом:

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <system.webServer> 
    <aspNetCore ... forwardWindowsAuthToken="true" /> 
    </system.webServer> 
</configuration>