Fer*_*mez 5 c# dependency-injection asp.net-core
我有一个 ASP.NET Core 3 应用程序,并且使用 AzureAD 进行身份验证。我的 Startup.ConfigureSerivces 方法中有以下几行,其目的是在附加 cookie 时执行一些业务规则。
services.Configure<CookiePolicyOptions>(options => {
options.CheckConsentNeeded = ctx => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
options.OnAppendCookie = ctx => {
var svc = ctx.Context.RequestServices.GetRequiredService<IUserInformationService>();
// do something with svc
};
});
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => {
Configuration.Bind("AzureAd", options);
});
Run Code Online (Sandbox Code Playgroud)
这效果很好,我IUserInformationService按照方法中的预期获得了注入的对象OnAppendCookie,并且 AzureAD 信息取自 appsettings.json。
然而最近,有关 AzureAD 租户的信息不得驻留在 appsettings.json 中,而是我现在必须查阅数据库。我有一项服务已经查询数据库并获取 AD 设置。就像是:
public interface IAzureADConfiguration {
void Configure(AzureADOptions options);
}
Run Code Online (Sandbox Code Playgroud)
但是,我找不到在调用时检索注入的服务的方法AddAzureAD。我想要的是这样的:
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => {
var svc = ???
svc.Configure(options);
Configuration.Bind("AzureAd", options);
});
Run Code Online (Sandbox Code Playgroud)
因为我无法HttpContext像AddAzureAD在OnAppendCookie. 现阶段有办法获取注入的对象吗?我不想对实例进行硬编码,因为此要求将来可能会发生变化(即添加另一种方法来配置我获取 Azure 广告设置的位置)。提前致谢!
感谢 @Nkosi 指出相关文档:使用 DI 服务配置选项
他们的回答让我开始走上正轨,但提供的代码示例对我不起作用,因为它没有考虑命名选项(AzureAD 配置使用的选项)。在弄清楚这一点并进行了一些简化之后,我最终得到了以下结果......
对于AzureADOptions,最好的选择似乎是添加一个后配置以在提供给 的现有(必需)配置回调之后运行AddAzureAD。两个回调将传递同一个AzureADOptions实例,因此现有回调可以按原样保留以加载“基本”值,并且配置后回调可以根据需要覆盖它们。
// Configure Azure AD to load settings from the app config.
// This is unchanged (apart from syntax) from the original question.
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options));
// Add a post-configure callback to augment the app config-provided values
// with service-provided values.
services.AddOptions<AzureADOptions>(AzureADDefaults.AuthenticationScheme)
.PostConfigure<IAzureADConfiguration>((options, service) =>
service.Configure(options));
Run Code Online (Sandbox Code Playgroud)
如果您不想从应用程序配置加载基值,只需替换Configuration.Bind("AzureAD", options)为空块 ( { })。
AddAzureAD使用命名选项实例,因此请务必将相同的名称传递给PostConfigure和AddAuthentication。如果两个地方没有使用相同的名称,则配置后回调将不会配置正确的选项实例(或者根本不会运行)。
注意:如果有人想使用此答案来配置 Azure AD 以外的其他内容...当没有注册现有选项实例或回调时,您应该使用该Configure方法而不是PostConfigure,并且可能不需要提供名称。
services.AddOptions<MyOptionsType>()
.Configure<IMyConfigurationService>((options, service) =>
service.Configure(options));
Run Code Online (Sandbox Code Playgroud)
虽然这不是您问题的直接答案,但它可能是引发您问题的问题的可行解决方案。
您可以实现自定义配置提供程序来从数据库加载设置,而不是编写配置服务。然后,您应该能够AddAzureAD使用 来保持通话原样Configuration.Bind。
文档中的示例new提供了 EF 数据上下文,而不是由 DI 容器提供。这违背了 DI 的本能,但我认为在这种情况下这很好。示例提供程序是一个小型且包含良好的子系统。它的数据库配置仍然被注入(尽管不是通过 DI 容器),并且仍然可以通过注入 EF 内存数据库的配置来进行单元测试。它没有任何其他需要交换的依赖项。DI 容器不会增加太多价值——系统已经拥有它需要的所有依赖注入。
| 归档时间: |
|
| 查看次数: |
2979 次 |
| 最近记录: |