c# - 在.net core web API中自动添加策略属性

标签 c# asp.net-core asp.net-core-webapi asp.net-core-2.1

我正在使用 .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);
        }
    }
}

最佳答案

您可以使用 custom convention为此,它允许自定义 application model 。使用约定可以让您自动向项目中的每个操作添加过滤器,使用所述约定的全局注册或使用操作上的属性来应用它,等等。

以下是适合您的自定义约定的示例实现:

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 级别的属性应用,以便您可以更具选择性,则可以实现一个自定义 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因此,它是为每个 Controller 而不是每个操作调用的。
  2. Apply收到一个 ControllerModel,因此我们迭代其所有操作并将 AuthorizeFilter 应用于这些操作。
  3. 它扩展了Attribute,以便它可以作为属性应用。

使用此方法时,不需要在 Startup.ConfigureServices 中添加约定 - 相反,可以将其添加为属性。例如:

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

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

关于c# - 在.net core web API中自动添加策略属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53149453/

相关文章:

c# - Xamarin Forms - 检查 Environment.SpecialFolder.DesktopDirectory 中是否存在文件

asp.net-core - NPoco 在 .net Core 中的使用

c# - System.ObjectDisposeException : Cannot access a disposed object. 对象名称: 'Cannot access a closed file.'

c# - 在大文本文件中用\r\n 替换\n

c# - 图像的分离和分析

c# - WCF - 使用 NetHttpBinding(WebSockets) 或替代双工绑定(bind)发送 JSON

c# - 文件夹未复制到输出目录

c# - .Net 核心依赖 - Bower

c# - 同一解决方案中两个 ASP.NET Core 项目之间的通信

c# - 如何在 Web API Controller 中使用分层架构处理服务器错误