Dependency Injection on Authorization Policy

前端 未结 3 1206
滥情空心
滥情空心 2021-01-19 16:08

I want to create a claim based authorization for my ASP.NET Core app:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthorizat         


        
相关标签:
3条回答
  • 2021-01-19 16:11

    To supplement the provided answer by @MichaelShterenberg, the configuration delegate can use a IServiceProvider to allow for additional dependencies

    public static IServiceCollection AddAuthorization(this IServiceCollection services,
        Action<AuthorizationOptions, IServiceProvider> configure) {
        services.AddOptions<AuthorizationOptions>().Configure<IServiceProvider>(configure);
        return services.AddAuthorization();
    }
    

    Which, based on the original example, can be used

    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())
            );
        });
    
        //...
    }
    

    If there were other dependencies needed, they could be resolved from the service provider.

    0 讨论(0)
  • 2021-01-19 16:27

    Thanks to Nkosi for the tip!

    Since AddAuthorization is basically configuring AuthorizationOptions behind the scenes, I followed the same pattern only I used OptionsBuilder to configure options with dependencies

    I created my own AddAuthorization method that accepts dependencies:

     public static IServiceCollection AddAuthorization<TDep>(
         this IServiceCollection services,
         Action<AuthorizationOptions, TDep> configure) where TDep : class
     {
         services.AddOptions<AuthorizationOptions>().Configure<TDep>(configure);
         return services.AddAuthorization();
     }
    

    And now I can use it to properly configure the requirement:

    services.AddAuthorization<IEmployeeProvider>((options, employeeProvider> =>
    {
        options.AddPolicy("Founders", policy =>
            policy.RequireClaim("EmployeeNumber", employeeProvider.GetAuthorizedEmployeeIds())
        );
    });
    

    You can follow the same technique if you need more dependencies (OptionsBuilder.Configure supports up to 5 dependencies)

    Obviously, this solution requires extra validation when upgrading to newer ASP versions, as the underlying implementation of AddAuhtorization may change

    0 讨论(0)
  • 2021-01-19 16:34

    You can build a service provider using the BuildServiceProvider() method on the IServiceCollection:

    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);
        }
    

    interface and Class

    public interface IEmployeeProvider
    {
        string[] GetAuthorizedEmployeeIds();
    }
    
    public class EmployeeProvider : IEmployeeProvider
    {
        public string[] GetAuthorizedEmployeeIds()
        {
            var data = new string[] { "1", "2", "3", "4", "5" };
            return data;
        }
    }
    
    0 讨论(0)
提交回复
热议问题