在 AddOpenIdConnect 中获取 ServiceProvider,无需 BuildServiceProvider()

Jul*_*ian 7 c# dependency-injection openid-connect asp.net-core asp.net-core-3.1

有没有一个好的方法可以获取 DIServiceProvider容器AddOpenIdConnect或者稍后配置 ClientSecret,以便我们完全设置 DI 容器?(例如在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();

Run Code Online (Sandbox Code Playgroud)

笔记

对于像OnValidatePrincipal我们这样的事件,我们可以从CookieValidatePrincipalContext.HttpContext.RequestServices

使用services.BuildServiceProvider()会给出这样的警告:

警告“从应用程序代码调用‘BuildServiceProvider’会导致创建单例服务的附加副本”

Kir*_*kin 6

身份验证的配置系统使用选项模式。这意味着以下方法将与您的问题中显示的方法具有类似的效果:

services.AddAuthentication()
    .AddOpenIdConnect(AuthenticationScheme, options =>
    {
        // ...
    });

services.Configure<OpenIdConnectOptions>(AuthenticationScheme, options =>
{
    options.ClientSecret = "ClientSecret";
});
Run Code Online (Sandbox Code Playgroud)

这很有用,因为选项模式支持 DI,使用如下所示的内容:

services.AddOptions<OpenIdConnectOptions>(AuthenticationScheme)
    .Configure<ISecretRetriever>((options, secretRetriever) =>
    {
        options.ClientSecret = secretRetriever.GetClientSecret();
    });
Run Code Online (Sandbox Code Playgroud)

要访问Configure适用于 DI 的方法,您必须首先调用AddOptions. 在此示例中,Configure给出了一个类型参数,它表示所需的依赖项。这将作为第二个参数传递到您的配置回调中,位于OpenIdConnectOptions正在配置的实例之后。