2017-12-05 21 views
0

기본 종속성 주입 컨테이너를 사용하여 쿠키 인증 옵션을 사용하여 ASP.Net 핵심 응용 프로그램에 쿠키 인증을 추가하는 경우. 시작 후 실행시 인증 옵션을 어떻게 대체 할 수 있습니까? 예를 들어 앱이 실행되는 동안 쿠키 만료를 변경하려고합니다. 변경에 영향을 미치기 위해 인증 처리자를 옵션으로 대체하는 방법을 알 수 없습니다. 인증을 대체하기 위해 런타임에런타임에 쿠키 인증 처리기 스키마 옵션 바꾸기

public static IServiceCollection ConfigureOAuth(this IServiceCollection services) 
{ 
    var appSettings = services.BuildServiceProvider().GetService<IOptions<AppSettings>>(); 

    return services.AddAuthentication(o => 
    { 
     o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; 
     o.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; 
    }) 
    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, (o) => 
    { 
     o.ExpireTimeSpan = TimeSpan.FromHours(appSettings.Value.HostOptions.SessionLifespanHours); 
    }) 
    .Services; 
} 

코드 : 시작시

코드 인증을 추가

/// <summary> 
/// Replace authentication options with new ones read from configuration. 
/// 1). Remove old services 
/// 2.) Reload the configuration 
/// 3.) Add the authentication scheme with options read from the latest configuration 
/// </summary> 
private static void ReplaceServices(IServiceCollection services, IHostingEnvironment env) 
{ 
    ClearServices(services); 

    services.Configure<AppSettings>(StartupConfiguration.BuildConfigurationRoot(env).GetSection("App")); 

    var provider = services.BuildServiceProvider(); 
    var appSettings = provider.GetService<IOptions<AppSettings>>(); 

    services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<CookieAuthenticationOptions>, PostConfigureCookieAuthenticationOptions>()); 
    services.AddScheme<CookieAuthenticationOptions, CookieAuthenticationHandler>(CookieAuthenticationDefaults.AuthenticationScheme, (o) => 
    { 
     o.ExpireTimeSpan = TimeSpan.FromHours(appSettings.Value.HostOptions.SessionLifespanHours); 
    }); 
} 

/// <summary> 
/// Clear stale dependencies: application settings configured from appsettings.json, 
/// authentication options and cookie authentication handler and options 
/// </summary> 
private static void ClearServices(IServiceCollection services) 
{ 
    var staleTypes = new List<Type> 
    { 
     typeof(IConfigureOptions<AppSettings>), 
     typeof(IConfigureOptions<AuthenticationOptions>), 
     typeof(IPostConfigureOptions<CookieAuthenticationOptions>), 
     typeof(IConfigureOptions<CookieAuthenticationOptions>), 
     typeof(CookieAuthenticationHandler) 
    }; 

    foreach (var staleType in staleTypes) 
    { 
     var staleService = services.FirstOrDefault(s => s.ServiceType.Equals(staleType)); 
     services.Remove(staleService); 
    } 
} 

답변

0

Asp.net 코어 기본 구성 재로드는 조금 색다른 될 수 있습니다. 서비스가 런타임에 변경되는 응용 프로그램 설정에 의존하는 경우 시작시 IOptions로 해당 설정을 주입 할 필요가 없습니다. 또 다른 방법은 파일 시스템 감시자로부터 이벤트 알림을 받으면 캐시 된 설정 사본을 다시로드하는 설정 공급자를 작성하는 것입니다. 이 접근 방식은 구성을 DI 서비스로 만들 필요가 없으며 더 이상 다시로드 토큰에 의존 할 필요가 없습니다. 흐름은 다음과 같이 진행됩니다.

  1. 앱 설정 읽기 및 저장을 캡슐화하는 구성 제공자 서비스를 만듭니다. init에서는 appsettings.json을 읽고 IConfigurationRoot의 인스턴스를 캐시합니다.
  2. 파일 시스템에서 앱 설정 변경 사항을 캡슐화하기 위해 다른 서비스를 만듭니다. 변경된 경우 FileChangeEvent가있는 간단한 pub/sub 패턴을 사용하여 구성 제공자에게 알립니다. 구성 공급자는 구성 루트를 업데이트 한 다음 구성을 새로 고치면 ConfigChangeEvent를 트리거 할 수 있습니다.
  3. 인증 옵션과 같은 라이브 구성에 의존하는 서비스는 ConfigChangeEvent에 가입하고 config 루트에서 필요한 섹션을 기반으로 설정을 업데이트 할 수 있습니다.

여기서 중요한 것은 인증 처리기가 성공적으로 사용할 수있는 옵션 서비스를 만들고 항상 실제 값을가집니다. 이렇게하려면 IOptionsMonitor를 구현해야합니다.

public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddAuthentication(o => 
    { 
     o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; 
     o.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; 
    }) 
    .AddSingleton<IOptionsMonitor<CookieAuthenticationOptions>, CookieAuthenticationConfigurator>() 
    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme); 
} 

IOptionsMonitor의 된 구현 :

{ 
    internal class CookieAuthenticationConfigurator : IOptionsMonitor<CookieAuthenticationOptions> 
    { 
     private readonly FileConfigurationBuilder ConfigProvider; 
     private readonly IHostingEnvironment Environment; 
     private readonly IDataProtectionProvider DataProtectionProvider; 
     private readonly IMessageHub Hub; 

     public CookieAuthenticationConfigurator(FileConfigurationBuilder configProvider, IDataProtectionProvider dataProtectionProvider, IMessageHub hub, IHostingEnvironment environment) 
     { 
      ConfigProvider = configProvider; 
      Environment = environment; 
      DataProtectionProvider = dataProtectionProvider; 
      Hub = hub; 
      Initialize(); 
     } 

     private void Initialize() 
     { 
      Hub.Subscribe<ConfigurationChangeEvent>(_ => 
      { 
       Build(); 
      }); 

      Build(); 
     } 

     private void Build() 
     { 
      var hostOptions = ConfigProvider.Get<HostOptions>("HostOptions"); 
      options = new CookieAuthenticationOptions 
      { 
       ExpireTimeSpan = TimeSpan.FromHours(hostOptions.SessionLifespanHours) 
      }; 
     } 

     private CookieAuthenticationOptions options; 

     public CookieAuthenticationOptions CurrentValue => options; 

     public CookieAuthenticationOptions Get(string name) 
     { 
      PostConfigureCookieAuthenticationOptions op = new PostConfigureCookieAuthenticationOptions(DataProtectionProvider); 
      op.PostConfigure(name, options); 
      return options; 
     } 

     public IDisposable OnChange(Action<CookieAuthenticationOptions, string> listener) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
}