NullReferenceException в DefaultUserSession при загрузке проекта с IdentityServer4 - PullRequest
0 голосов
/ 08 декабря 2018

Я использую приложение Dotnet Core 2.2 с IdentityServer4, установленным с помощью Nuget.Когда я собираю докер-контейнер и запускаю, все работает нормально.При развертывании этого контейнера в моем кластере Google Kubernetes Engine происходит сбой при запуске со следующим:

{
 insertId:  "18ykz2ofg4ipm0"  
 labels: {
  compute.googleapis.com/resource_name:  "fluentd-gcp-v3.1.0-nndnb"   
  container.googleapis.com/namespace_name:  "my_namespace"   
  container.googleapis.com/pod_name:  "identity-deployment-5b8bd8745b-qn2v8"   
  container.googleapis.com/stream:  "stdout"   
 }
 logName:  "projects/my_project/logs/app"  
 receiveTimestamp:  "2018-12-07T21:09:25.708527406Z"  
 resource: {
  labels: {
   cluster_name:  "my_cluster"    
   container_name:  "app"    
   instance_id:  "4238697312444637243"    
   namespace_id:  "my_namespace"    
   pod_id:  "identity-deployment-5b8bd8745b-qn2v8"    
   project_id:  "my_project"    
   zone:  "europe-west2-b"    
  }
  type:  "container"   
 }
 severity:  "INFO"  
 textPayload:  "System.NullReferenceException: Object reference not set 
to an instance of an object.
   at 
IdentityServer4.Services.DefaultUserSession.RemoveSessionIdCookieAsync()
   at 
IdentityServer4.Services.DefaultUserSession.EnsureSessionIdCookieAsync()
   at 
IdentityServer4.Hosting.IdentityServerMiddleware.Invoke(HttpContext context, IEndpointRouter router, IUserSession session, IEventService events) 
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at IdentityServer4.Hosting.BaseUrlMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
"  
 timestamp:  "2018-12-07T21:09:17Z"  
}

Как я уже говорил, это работает идеально локально, а при работе внутри контейнера Docker, только когда в Kubernetes делаютЯ вижу эти ошибки.

Я не уверен, что я пропустил здесь с kubernetes, но любая помощь очень ценится.

1 Ответ

0 голосов
/ 25 мая 2019

Это раздражало меня в последние несколько дней.Я подозреваю, что это как-то связано с недавним устареванием прежнего механизма в конфигурации компоновщика приложений:

   app.UseAuthentication().UseCookieAuthentication();  <-- no longer valid and apparently will not even compile now.

Это было заменено следующим в разделе ConfigureServices:

  services.AddAuthentication("YourCookieName")
    .AddCookie("YourCookieName", options =>
    {
      options.ExpireTimeSpan = TimeSpan.FromDays(30.0);
    });

ХотяЯ не уверен, каково точное критическое изменение для identityserver4, после клонирования компонентов identityserver4 и отладки я смог изолировать конструктор для DefaultUserSession, принимающий IHttpContextAccessor, который получал значение null:

Рассматриваемый конструктор:

    public DefaultUserSession(
        IHttpContextAccessor httpContextAccessor,
        IAuthenticationSchemeProvider schemes,
        IAuthenticationHandlerProvider handlers,
        IdentityServerOptions options,
        ISystemClock clock,
        ILogger<IUserSession> logger)
    { ...

Следующее решение устраняет эту ошибку, хотя мы надеемся, что identityserver4 сделает этот вопрос в ближайшем будущем.

Вам необходимо добавить службу IHttpContextAccessor в ConfigureServices:

public override void ConfigureServices(IServiceCollection services)
{
  ... other code omitted ...
  services.AddScoped<IHttpContextAccessor>(provider => new 
       LocalHttpContextAccessor(provider));
  ... other code omitted ...
}

LocalHttpContextAccessor - это просто закрытый класс в классе конфигурации, как показано здесь:

private class LocalHttpContextAccessor : IHttpContextAccessor
{
  public IServiceProvider serviceProvider { get; private set; }
  public HttpContext httpContext { get; set; }

  public LocalHttpContextAccessor(IServiceProvider serviceProvider)
  {
    this.serviceProvider = serviceProvider;
    this.httpContext = null;
  }

  public HttpContext HttpContext
  {
    get
    {
      return this.httpContext;
    }
    set
    {
      this.httpContext = null;
    }
  }
}

Проблема в том, что на этапе настройки служб не существует текущего контекста для установки, поэтому яустановить его в блоке использованияна этапе настройки компоновщика приложений:

public override void Configure(IApplicationBuilder app,
  IHostingEnvironment env)
{
  app.Use(async (context, next) =>
  {
    IHttpContextAccessor httpContextAccessor;

    httpContextAccessor = context.RequestServices.GetRequiredService<IHttpContextAccessor>();
    if (httpContextAccessor is LocalHttpContextAccessor)
    {
      ((LocalHttpContextAccessor)httpContextAccessor).httpContext = context;
    }
    await next();
  });
  ... other code omitted ...
  app.UseIdentityServer();

Это установит контекст http до запуска кода сервера идентификации, который устраняет ошибку.Области обслуживания должны создаваться индивидуально для каждого запроса.Я только недавно полностью изучил ядро ​​.net из среды .net, поэтому, если в этом коде есть проблемы с областью действия или DI, которые могут привести к утечкам или плохому жизненному циклу, я был бы признателен за вводную информацию.Тем не менее, по крайней мере, этот код предотвращает сбой сервера идентификации 4 с ядром 2.2 +.

...