我想为我的ASP.NET Core应用创建基于声明的授权:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthorization(options =>
{
options.AddPolicy("Founders", policy =>
policy.RequireClaim("EmployeeNumber", "1", "2", "3", "4", "5"));
});
}
问题是我有一种非平凡的方法来解析员工人数(1到5),并且我想使用DI服务:
public interface IEmployeeProvider {
string[] GetAuthorizedEmployeeIds();
}
我想注入此服务并在AddPolicy中使用它,例如:
services.AddAuthorization(options =>
{
options.AddPolicy("Founders", policy =>
policy.RequireClaim("EmployeeNumber", *employeeProvider.GetAuthorizedEmployeeIds()));
});
注意
我知道我可以编写自己的AuthorizationHandler,可以在其中轻松注入IEmployeeProvider
,但是我反对这种模式,因为:
所以我正在寻找一种在构建策略时注入服务的方法
答案 0 :(得分:1)
感谢Nkosi的提示!
由于AddAuthorization基本上是在幕后配置AuthorizationOptions
,所以我遵循相同的模式,只是使用OptionsBuilder
来配置具有依赖项的选项
我创建了自己的接受依赖关系的AddAuthorization方法:
public static IServiceCollection AddAuthorization<TDep>(
this IServiceCollection services,
Action<AuthorizationOptions, TDep> configure) where TDep : class
{
services.AddOptions<AuthorizationOptions>().Configure<TDep>(configure);
return services.AddAuthorization();
}
现在我可以使用它来正确配置需求:
services.AddAuthorization<IEmployeeProvider>((options, employeeProvider> =>
{
options.AddPolicy("Founders", policy =>
policy.RequireClaim("EmployeeNumber", employeeProvider.GetAuthorizedEmployeeIds())
);
});
如果需要更多的依赖项(OptionsBuilder.Configure
最多支持5个依赖项),则可以采用相同的技术
很明显,此解决方案在升级到更新的ASP版本时需要额外的验证,因为AddAuhtorization
的基础实现可能会更改
答案 1 :(得分:0)
要通过@MichaelShterenberg补充所提供的答案,配置委托可以使用IServiceProvider
来允许其他依赖项
public static IServiceCollection AddAuthorization(this IServiceCollection services,
Action<AuthorizationOptions, IServiceProvider> configure) {
services.AddOptions<AuthorizationOptions>().Configure<IServiceProvider>(configure);
return services.AddAuthorization();
}
根据原始示例,可以使用
public void ConfigureServices(IServiceCollection services) {
//...
service.AddScoped<IEmployeeProvider, EmployeeProvider>();
services.AddAuthorization((options, sp) => {
IEmployeeProvider employeeProvider = sp.GetRequiredService<IEmployeeProvider>();
options.AddPolicy("Founders", policy =>
policy.RequireClaim("EmployeeNumber", employeeProvider.GetAuthorizedEmployeeIds())
);
});
//...
}
如果需要其他依赖项,可以从服务提供商处解决。
答案 2 :(得分:-1)
您可以使用IServiceCollection上的BuildServiceProvider()方法来构建服务提供商:
$> cd D
$> git remote add A "path to A"
$> git remote update
界面和类
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IEmployeeProvider, EmployeeProvider>();
var sp = services.BuildServiceProvider();
var employeeProvider = sp.GetService<IEmployeeProvider>();
string[] values = employeeProvider.GetAuthorizedEmployeeIds();
services.AddAuthorization(options =>
{
options.AddPolicy("Founders", policy =>
policy.RequireClaim("EmployeeNumber", employeeProvider.GetAuthorizedEmployeeIds()));
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}