以编程方式保护 ASP controllers/methods

Secure ASP controllers/methods programmatically

我在 API 之后,它允许从 API 应用 [Authorize] 属性,而不是将它放在控制器的 class/method.

考虑来自依赖 nuget 包的第三方控制器 类,我想将它们托管在我的应用程序中并为它们实现安全性。 我知道我可以使用

app.UseEndpoints(endpoints => { endpoints.MapControllers().RequireAuthorization(new AuthorizeAttribute("policy")); });

但这将配置 ALL 控制器和方法以受 policy 保护,我需要根据 class/method 进行控制。 使用

手动映射
 endpoints.MapPut("***").RequireAuthorization(new AuthorizeAttribute("someOtherPolicy"))

也不是一个选项,因为映射已经在导入的控制器上使用 [Microsoft.AspNetCore.Mvc.HttpPost, Microsoft.AspNetCore.Mvc.Route("api/someRoute")] 属性定义。

请指教

如果您可以确定应在哪个端点应用特定的授权策略,您可以尝试以下操作:

public class MyAuthorizationFilter: AuthorizeAttribute, IAsyncAuthorizationFilter
{
    public MyAuthorizationFilter() : base()
    {
        //this.AuthenticationSchemes = "";
        //this.Policy = "";
        //this.Roles = "";
    }

    public Task OnAuthorizationAsync(AuthorizationFilterContext context)
    {
        context.Result = new OkObjectResult("my custom policy was checked");

        return Task.CompletedTask;
    }
}

public static class DynamicAuthorizationPolicies
{
    public static void RegisterMyFilters(this IServiceProvider serviceProvider)
    {
        var allEndpoints = serviceProvider
            .GetService<IActionDescriptorCollectionProvider>()
            ?.ActionDescriptors
            ?.Items;

        if (allEndpoints is null)
        {
            return;
        }

        foreach (var endpoint in allEndpoints)
        {
            // If you debug hier you will see that you can register 
            // differnt filters or attribute in different collections 
            // for the endpoint
            if (/*endpoint match some requirement*/true)
            {
                var authorizeFilter = serviceProvider.GetService<MyAuthorizationFilter>();
                var descriptor = new FilterDescriptor(authorizeFilter, FilterScope.Action);

                endpoint.FilterDescriptors.Add(descriptor);
            }
        }
    }
}

... 这是用法:

public void ConfigureServices(IServiceCollection services)
{
    // services.Add...

    services.AddTransient<MyAuthorizationFilter>();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // app.Use....

    app.ApplicationServices.RegisterMyFilters();
}