2017-12-05 5 views
0

ネイティブ依存性注入コンテナを使用してCookie認証オプションを使用してASP.NetコアアプリケーションにCookie認証を追加するとします。起動後に実行時に認証オプションをどのように置き換えることができますか?たとえば、アプリの実行中にCookieの有効期限を変更する場合などです。変更に影響を与えるために、認証ハンドラとオプションの両方を置き換える方法を理解できません。認証を置き換えるために、実行時に実行時にCookie認証ハンドラスキームオプションを置換する

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を購読して、設定ルートから必要なセクションに基づいて設定を更新できます。

ここで重要な点は、認証ハンドラが正常に使用でき、常に有効な値を持つオプションサービスを作成することです。これを行うには、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のimplemenation:

{ 
    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(); 
     } 
    } 
} 
関連する問題