问题
I try to define an authorization policy to be applied in all methods of all my controllers. I am trying to follow the guidelines given here, in "Authorization for specific endpoints" subsection to substitute my previous AuthorizeFilter
but it does not work.
In my Startup
I have:
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute().RequireAuthorization();
});
In ConfigureServices
:
services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
.AddAzureADBearer(options => this.Configuration.Bind("AzureAd", options));
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.AddRequirements(new MyRequirement(MyParams))
.Build();
});
(...)
services.AddTransient<IAuthorizationHandler, MyAuthorizationHandler>();
And I have a Requirement:
public class MyRequirement : IAuthorizationRequirement
{
public EntityType MyParams { get; private set; }
public MyRequirement(MyParams myParams) { MyParams = myParams; }
}
and a Handler:
public class MyAuthorizationHandler : AuthorizationHandler<MyRequirement>
{
private readonly ILogger<MyAuthorizationHandler> logger;
private readonly IHttpContextAccessor httpContextAccessor;
public MyAuthorizationHandler(IHttpContextAccessor httpContextAccessor, ILogger<MyAuthorizationHandler> logger)
{
this.httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
this.logger = logger;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MyRequirement requirement)
{
---> Some things. I don't get here when I debug.
}
}
In my controllers I do NOT put any decorator, because I want to apply this authorization policy to ALL my methods, and that's why I override the DefaultPolicy
.
If I debug, I do not stop at the Handler as I expect. Actually, if I put a decorator [Authorize]
in the controller, I do stop there but, as I mentioned, I'm trying to avoid having to write this decorator in all the controllers.
Why is is not working? Thank you!
回答1:
My understanding is that the [Authorize]
attribute is required in order to use even the default policy. What I normally do when I need to protect all my endpoints in this way is to create an abstract base controller with this attribute and then have my other controllers inherit from this.
For example:
Base controller
[Authorize]
public abstract class MyBaseController : Controller //use Controller for mvc controller or ControllerBase for api controller
{
//base controller methods and properties
}
Other controllers:
public class MyOtherController : MyBaseController
{
//controller methods and properties
}
回答2:
Try this:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddTransient<IAuthorizationHandler, MyAuthorizationHandler>();
services.AddControllersWithViews(config =>
{
var policy = new AuthorizationPolicyBuilder()
.AddRequirements(new MyRequirement(MyParams))
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
});
services.AddDbContext<MvcProj3Context>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MvcProj3Context")));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthentication();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
来源:https://stackoverflow.com/questions/59503646/trying-to-apply-an-authorisation-filter-in-all-my-controllers-bug-iauthorization