Asp.Net Core 2 在 运行 时间替换服务集合中的 Open Id Authentication 选项
Asp.Net Core 2 Replace Open Id Authentication options in service collection at run time
您将如何替换 Asp.Net Core 2.0 中 IServiceCollection 中的身份验证选项?
在配置服务中:
AddAuthentication((o) =>
{
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
}).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, (o) =>
{
o.LoginPath = Constants.LoginPath;
}).AddOpenIdConnect(ConfigureOpenIdConnectProvider);
假设我的客户端 ID 在 运行 时间发生了变化,我想重新加载配置,所以我会观察 appsettings.json.
中的变化
通过删除配置并将其添加回服务来替换配置不会应用配置。
Configuration.GetReloadToken().RegisterChangeCallback(OnConfigurationChanged(authServices), new Object());
private Action<object> OnConfigurationChanged(IServiceCollection authServices)
{
return o =>
{
Action<OpenIdConnectOptions> action = ConfigureOpenIdConnectProvider;
//Replace the existing open id connection options
authServices.Remove(authServices.FirstOrDefault(s => typeof(IConfigureOptions<OpenIdConnectOptions>).Equals(s.ServiceType)));
authServices.Configure(OpenIdConnectDefaults.AuthenticationScheme, action);
};
}
private void ConfigureOpenIdConnectProvider(OpenIdConnectOptions opts)
{
var provider = Configuration.GetSection("OAuthClientProvider").Get<OAuthClientProvider>();
opts.ClientId = provider.ClientId;
opts.ClientSecret = provider?.ClientSecret ?? string.Empty;
opts.Authority = provider.Authority;
}
如何在运行时间内添加新方案:
private void AddGoogleScheme(IApplicationBuilder app)
{
var googleHandlerType = typeof(GoogleOptions).Assembly.GetType("Microsoft.AspNetCore.Authentication.Google.GoogleHandler");
var provider = app.ApplicationServices.GetService<IAuthenticationSchemeProvider>();
provider.AddScheme(new AuthenticationScheme("Google", "Google", googleHandlerType));
}
我们可以创建自己的配置,但不需要 Google 配置。因此,您可以删除 Google configure:
var googleConfigureOptions = services.SingleOrDefault(x => x.ServiceType == typeof(IConfigureOptions<GoogleOptions>));
services.Remove(googleConfigureOptions);
您必须创建并注册配置选项:
builder.Services.AddTransient<IConfigureOptions<GoogleOptions>, OpenIdConnectConfigurator<GoogleOptions>>();
配置选项的实现:
internal class OpenIdConnectConfigurator<TOptions> : IConfigureNamedOptions<TOptions> where TOptions : RemoteAuthenticationOptions
{
public void Configure(TOptions options)
{
throw new InvalidOperationException();
}
public void Configure(string name, TOptions options)
{
if(name == "Google") // name == "YourScheme"
{
// you can get data from DB or other source
// options.ClientId = ...
// options.ClientSecret = ...
} else {
// Facebook or other IDP
}
}
}
如果您覆盖数据库中的选项(例如),那么您必须清除缓存。
为什么?
- Google handler继承AuthenticationHandler
在 AuthenticationHandler 中,我们有 InitializeAsync 方法。
InitializeAsync 方法从 OptionsMonitor 获取选项。
- OptionsMonitor 从缓存中获取选项或创建新选项并添加到
缓存。
当然要写成clean/better的样子:)
例如:您可以创建自己的 AddGoogle() 方法来注册所有内容(这样您就不需要在 Startup 中使用任何 IDP)。
以上所有代码都应该表明您必须这样做。如果您有任何疑问,请告诉我:)
您将如何替换 Asp.Net Core 2.0 中 IServiceCollection 中的身份验证选项?
在配置服务中:
AddAuthentication((o) =>
{
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
}).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, (o) =>
{
o.LoginPath = Constants.LoginPath;
}).AddOpenIdConnect(ConfigureOpenIdConnectProvider);
假设我的客户端 ID 在 运行 时间发生了变化,我想重新加载配置,所以我会观察 appsettings.json.
中的变化通过删除配置并将其添加回服务来替换配置不会应用配置。
Configuration.GetReloadToken().RegisterChangeCallback(OnConfigurationChanged(authServices), new Object());
private Action<object> OnConfigurationChanged(IServiceCollection authServices)
{
return o =>
{
Action<OpenIdConnectOptions> action = ConfigureOpenIdConnectProvider;
//Replace the existing open id connection options
authServices.Remove(authServices.FirstOrDefault(s => typeof(IConfigureOptions<OpenIdConnectOptions>).Equals(s.ServiceType)));
authServices.Configure(OpenIdConnectDefaults.AuthenticationScheme, action);
};
}
private void ConfigureOpenIdConnectProvider(OpenIdConnectOptions opts)
{
var provider = Configuration.GetSection("OAuthClientProvider").Get<OAuthClientProvider>();
opts.ClientId = provider.ClientId;
opts.ClientSecret = provider?.ClientSecret ?? string.Empty;
opts.Authority = provider.Authority;
}
如何在运行时间内添加新方案:
private void AddGoogleScheme(IApplicationBuilder app)
{
var googleHandlerType = typeof(GoogleOptions).Assembly.GetType("Microsoft.AspNetCore.Authentication.Google.GoogleHandler");
var provider = app.ApplicationServices.GetService<IAuthenticationSchemeProvider>();
provider.AddScheme(new AuthenticationScheme("Google", "Google", googleHandlerType));
}
我们可以创建自己的配置,但不需要 Google 配置。因此,您可以删除 Google configure:
var googleConfigureOptions = services.SingleOrDefault(x => x.ServiceType == typeof(IConfigureOptions<GoogleOptions>));
services.Remove(googleConfigureOptions);
您必须创建并注册配置选项:
builder.Services.AddTransient<IConfigureOptions<GoogleOptions>, OpenIdConnectConfigurator<GoogleOptions>>();
配置选项的实现:
internal class OpenIdConnectConfigurator<TOptions> : IConfigureNamedOptions<TOptions> where TOptions : RemoteAuthenticationOptions
{
public void Configure(TOptions options)
{
throw new InvalidOperationException();
}
public void Configure(string name, TOptions options)
{
if(name == "Google") // name == "YourScheme"
{
// you can get data from DB or other source
// options.ClientId = ...
// options.ClientSecret = ...
} else {
// Facebook or other IDP
}
}
}
如果您覆盖数据库中的选项(例如),那么您必须清除缓存。 为什么?
- Google handler继承AuthenticationHandler
在 AuthenticationHandler 中,我们有 InitializeAsync 方法。
InitializeAsync 方法从 OptionsMonitor 获取选项。
- OptionsMonitor 从缓存中获取选项或创建新选项并添加到 缓存。
当然要写成clean/better的样子:) 例如:您可以创建自己的 AddGoogle() 方法来注册所有内容(这样您就不需要在 Startup 中使用任何 IDP)。 以上所有代码都应该表明您必须这样做。如果您有任何疑问,请告诉我:)