I'm using .net Core 2.1 Web API. I'm using action based authentication. So, I add every method [Authorize(Policy = ".....")]
like below. But, I don't want write every time. I want taking policy name from method name automatically. How can I achieve this?
namespace University.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class UniversityController : ControllerBase
{
private readonly IUniversityService universityService;
public UniversityController(IUniversityService universityService)
{
this.universityService = universityService;
}
[Authorize(Policy = "GetUniversities")]
[HttpGet("GetUniversities")]
public async Task<ServiceResult> GetUniversities()
{
return await universityService.GetUniversities();
}
[Authorize(Policy = "GetStudents")]
[HttpGet("GetStudents")]
public async Task<ServiceResult> GetStudents()
{
return await universityService.GetStudents();
}
[Authorize(Policy = "DeleteUniversity")]
[HttpGet("DeleteUniversity")]
public async Task<ServiceResult> DeleteUniversity(int universityId)
{
return await universityService.DeleteUniversity(universityId);
}
}
}
You can enable CORS per action, per controller, or globally for all Web API controllers in your application. To enable CORS for a single action, set the [EnableCors] attribute on the action method. The following example enables CORS for the GetItem method only.
The [ApiController] attribute applies inference rules for the default data sources of action parameters. These rules save you from having to identify binding sources manually by applying attributes to the action parameters.
You can use a custom convention for this, which allows for customisation of the application model. Using a convention allows you to add filters to each action within your project automatically, using either a global registration of said convention or by applying it using a attribute on the action, etc.
Here's a sample implementation of a custom convention for your purposes:
public class SomeActionModelConvention : IActionModelConvention
{
public void Apply(ActionModel model)
{
model.Filters.Add(new AuthorizeFilter(model.ActionName));
}
}
In this example, we implement IActionModelConvention
, which defines an Apply
method that is called by the MVC framework on initialisation. In the implementation above, we're simply adding an AuthorizeFilter
to the model that uses the action's name as the policy name.
In order to register the convention, add it via MvcOptions
in Startup.ConfigureServices
. e.g.:
services.AddMvc(options => options.Conventions.Add(new SomeActionModelConvention()));
As I suggested above, it's possible to register this using an attribute, but that doesn't make much sense in this scenario as you'd have to add the attribute to the action itself, which would defeat the purpose of something high-level like this convention.
However, if you want to apply this as an attribute at the controller level so that you can be more selective, you could implement instead a custom controller convention that does something very similar. Here's a sample for that:
public class SomeControllerModelConvention : Attribute, IControllerModelConvention
{
public void Apply(ControllerModel model)
{
foreach (var actionModel in model.Actions)
actionModel.Filters.Add(new AuthorizeFilter(actionModel.ActionName));
}
}
This is very similar to SomeActionModelConvention
, except for these three differences:
Apply
is handed a ControllerModel
, so we iterate through all of its actions and apply the AuthorizeFilter
to those.Attribute
so that it can be applied as an attribute.When using this approach, the convention does not need to be added in Startup.ConfigureServices
- instead, it can be added as an attribute. e.g.:
[Route("api/[controller]")]
[ApiController]
[SomeControllerModelConvention]
public class UniversityController : ControllerBase
...
Finally, if you want to apply the convention to controllers but do so using code, you could register the convention in Startup.ConfigureServices
(as with the SomeActionModelConvention
approach) and then customise the implementation of Apply
to only add the filter according to your own logic. I won't go into the details of that as I've already gone on for long enough.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With