在没有 BuildServiceProvider() 的情况下在 AddOpenIdConnect 中获取 ServiceProvider
Get ServiceProvider inside AddOpenIdConnect without BuildServiceProvider()
有没有什么好的方法可以在 AddOpenIdConnect
、 或 中获取 ServiceProvider
稍后在我们已完全设置 DI 容器的地方配置 ClientSecret? (例如 Configure(IApplicationBuilder app)
)
我们正在从其他地方获取客户端机密,我们喜欢为此使用 DI。
目前我们这样做,但我真的很想删除 services.BuildServiceProvider()
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddOpenIdConnect(AuthenticationScheme, options =>
{
ServiceProvider serviceProvider = services.BuildServiceProvider(); // we like to prevent this
options.ClientSecret = serviceProvider.GetRequiredService<ISecretRetriever>().GetClientSecret();
备注
对于像 OnValidatePrincipal
这样的事件,我们可以从 CookieValidatePrincipalContext.HttpContext.RequestServices
中获取
使用 services.BuildServiceProvider()
会给出这个警告:
warning "Calling 'BuildServiceProvider' from application code results in a additional copy of Singleton services being created"
认证配置系统使用Options pattern。这意味着以下方法将对您的问题中显示的方法产生 相似 效果:
services.AddAuthentication()
.AddOpenIdConnect(AuthenticationScheme, options =>
{
// ...
});
services.Configure<OpenIdConnectOptions>(AuthenticationScheme, options =>
{
options.ClientSecret = "ClientSecret";
});
这很有用,因为选项模式 supports DI,使用如下内容:
services.AddOptions<OpenIdConnectOptions>(AuthenticationScheme)
.Configure<ISecretRetriever>((options, secretRetriever) =>
{
options.ClientSecret = secretRetriever.GetClientSecret();
});
要访问使用 DI 的 Configure
方法,您必须先调用 AddOptions
。在此示例中,Configure
被赋予一个类型参数,它表示所需的依赖项。这将作为第二个参数传递到您的配置回调中,位于正在配置的 OpenIdConnectOptions
实例之后。
以柯克的回答为基础,提供更完整的示例
// Register our custom options -- we can resolve this as IOptions<MyCustomOptions>
services.Configure<MyCustomOptions>(config.GetSection(optionsSection));
// Configure OIDC
var authBuilder = services.AddAuthentication()
.AddOpenIdConnect(schemeName, options => ...);
// Update OIDC config with our custom options
authBuilder.Services.AddOptions<OpenIdConnectOptions>(schemeName)
.Configure<IOptions<MyCustomOptions>>((oidcOptions, myOptions) =>
{
oidcOptions.ClientSecret = myOptions.Value.SecretTime;
});
// register some other services
builder.Services.AddSingleton<Foo>(sp => {
var myOpts = sp.GetRequiredService<IOptions<MyCustomOptions>>();
new Foo(myOpts.Value.SecretTime)
};
有没有什么好的方法可以在 AddOpenIdConnect
、 或 中获取 ServiceProvider
稍后在我们已完全设置 DI 容器的地方配置 ClientSecret? (例如 Configure(IApplicationBuilder app)
)
我们正在从其他地方获取客户端机密,我们喜欢为此使用 DI。
目前我们这样做,但我真的很想删除 services.BuildServiceProvider()
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddOpenIdConnect(AuthenticationScheme, options =>
{
ServiceProvider serviceProvider = services.BuildServiceProvider(); // we like to prevent this
options.ClientSecret = serviceProvider.GetRequiredService<ISecretRetriever>().GetClientSecret();
备注
对于像 OnValidatePrincipal
这样的事件,我们可以从 CookieValidatePrincipalContext.HttpContext.RequestServices
使用 services.BuildServiceProvider()
会给出这个警告:
warning "Calling 'BuildServiceProvider' from application code results in a additional copy of Singleton services being created"
认证配置系统使用Options pattern。这意味着以下方法将对您的问题中显示的方法产生 相似 效果:
services.AddAuthentication()
.AddOpenIdConnect(AuthenticationScheme, options =>
{
// ...
});
services.Configure<OpenIdConnectOptions>(AuthenticationScheme, options =>
{
options.ClientSecret = "ClientSecret";
});
这很有用,因为选项模式 supports DI,使用如下内容:
services.AddOptions<OpenIdConnectOptions>(AuthenticationScheme)
.Configure<ISecretRetriever>((options, secretRetriever) =>
{
options.ClientSecret = secretRetriever.GetClientSecret();
});
要访问使用 DI 的 Configure
方法,您必须先调用 AddOptions
。在此示例中,Configure
被赋予一个类型参数,它表示所需的依赖项。这将作为第二个参数传递到您的配置回调中,位于正在配置的 OpenIdConnectOptions
实例之后。
以柯克的回答为基础,提供更完整的示例
// Register our custom options -- we can resolve this as IOptions<MyCustomOptions>
services.Configure<MyCustomOptions>(config.GetSection(optionsSection));
// Configure OIDC
var authBuilder = services.AddAuthentication()
.AddOpenIdConnect(schemeName, options => ...);
// Update OIDC config with our custom options
authBuilder.Services.AddOptions<OpenIdConnectOptions>(schemeName)
.Configure<IOptions<MyCustomOptions>>((oidcOptions, myOptions) =>
{
oidcOptions.ClientSecret = myOptions.Value.SecretTime;
});
// register some other services
builder.Services.AddSingleton<Foo>(sp => {
var myOpts = sp.GetRequiredService<IOptions<MyCustomOptions>>();
new Foo(myOpts.Value.SecretTime)
};