在.net核心web API中自动添加策略属性



我使用的是.net Core 2.1 Web API。我正在使用基于操作的身份验证。因此,我添加了每个方法[Authorize(Policy = ".....")],如下所示。但是,我不想每次都写。我想自动从方法名称中获取策略名称。我怎样才能做到这一点?

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

您可以为此使用自定义约定,从而允许自定义应用程序模型。使用约定可以自动为项目中的每个操作添加过滤器,使用所述约定的全局注册或使用操作上的属性应用它,等等。

以下是针对您的目的的自定义约定的示例实现:

public class SomeActionModelConvention : IActionModelConvention
{
public void Apply(ActionModel model)
{
model.Filters.Add(new AuthorizeFilter(model.ActionName));
}
}

在本例中,我们实现了IActionModelConvention,它定义了一个Apply方法,该方法在初始化时由MVC框架调用。在上面的实现中,我们只是将AuthorizeFilter添加到使用操作名称作为策略名称的模型中。

为了注册约定,请通过Startup.ConfigureServices中的MvcOptions将其添加。例如:

services.AddMvc(options => options.Conventions.Add(new SomeActionModelConvention()));

正如我上面所建议的,可以使用属性来注册,但在这种情况下,这没有多大意义,因为你必须将属性添加到动作本身,这将违背像这种约定这样的高级功能的目的。

但是,如果您想将其作为控制器级别的属性应用,以便更具选择性,您可以实现一个自定义的controller约定,该约定可以执行类似的操作。这里有一个例子:

public class SomeControllerModelConvention : Attribute, IControllerModelConvention
{
public void Apply(ControllerModel model)
{
foreach (var actionModel in model.Actions)
actionModel.Filters.Add(new AuthorizeFilter(actionModel.ActionName));
}
}

这与SomeActionModelConvention非常相似,除了以下三个区别:

  1. 它实现IControllerModelConvention,因此,它是为每个控制器而不是为每个操作调用的
  2. Apply得到了一个ControllerModel,所以我们迭代它的所有操作,并将AuthorizeFilter应用于这些操作
  3. 它扩展了Attribute,使其可以作为属性应用

使用此方法时,公约不需要在Startup.ConfigureServices中添加,而是可以作为属性添加。例如:

[Route("api/[controller]")]
[ApiController]
[SomeControllerModelConvention]
public class UniversityController : ControllerBase
...

最后,如果您想将约定应用于控制器,但使用代码执行,则可以在Startup.ConfigureServices中注册约定(与SomeActionModelConvention方法一样(,然后根据自己的逻辑自定义Apply的实现以仅添加过滤器。我不会详述,因为我已经讲了足够长的时间了。

相关内容

最新更新