在 .net 核心 Web API 中自动添加策略属性
Posted
技术标签:
【中文标题】在 .net 核心 Web API 中自动添加策略属性【英文标题】:Adding policy attribute automatically in .net core web API 【发布时间】:2019-04-08 12:30:18 【问题描述】:我正在使用 .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);
【问题讨论】:
【参考方案1】:您可以为此使用custom convention,它允许自定义application model。使用约定允许您自动为项目中的每个操作添加过滤器,使用所述约定的全局注册或使用操作上的属性应用它等。
这是一个自定义约定的示例实现,供您参考:
public class SomeActionModelConvention : IActionModelConvention
public void Apply(ActionModel model)
model.Filters.Add(new AuthorizeFilter(model.ActionName));
在本例中,我们实现了IActionModelConvention
,它定义了一个Apply
方法,该方法由MVC 框架在初始化时调用。在上面的实现中,我们只是将AuthorizeFilter
添加到使用操作名称作为策略名称的模型中。
要注册约定,请通过MvcOptions
将其添加到Startup.ConfigureServices
。例如:
services.AddMvc(options => options.Conventions.Add(new SomeActionModelConvention()));
正如我上面所建议的,可以使用属性来注册它,但在这种情况下这没有多大意义,因为您必须将属性添加到操作本身,这会破坏某些东西的目的-level 像这样的约定。
但是,如果您想将其作为 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
非常相似,除了这三个不同之处:
-
它实现了IControllerModelConvention,因此会为每个控制器而不是每个动作调用。
Apply
被传递给 ControllerModel
,因此我们遍历其所有操作并将 AuthorizeFilter
应用于这些操作。
它扩展了Attribute
,因此可以作为属性应用。
当使用这种方法时,约定确实不需要在Startup.ConfigureServices
中添加 - 相反,它可以作为属性添加。例如:
[Route("api/[controller]")]
[ApiController]
[SomeControllerModelConvention]
public class UniversityController : ControllerBase
...
最后,如果您想将约定应用于控制器但使用代码这样做,您可以在Startup.ConfigureServices
中注册约定(与SomeActionModelConvention
方法一样)然后自定义Apply
的实现以仅添加根据您自己的逻辑进行过滤。因为我已经讲了足够长的时间,所以我不会详细说明。
【讨论】:
感谢您的回复@KirkLarkin。它救了我。你的两个建议都很有效。但是,我无法选择其中之一。我应该更喜欢哪一个?在项目的未来,哪一个是可定制的?你对我的情况有什么想法? 如果我知道控制器中的所有操作都将使用操作名称作为策略名称,我会选择SomeControllerModelConvention
。您可以在每个控制器的基础上应用它(例如,如果某些控制器不需要授权,这很有用),或者,如果您知道它用于项目中的 所有 控制器,则可以如我所述,将其注册为约定。
再次感谢@KirkLarkin。例如 loginController 不需要你说的授权。所以,SomeControllerModelConvention 在这种情况下更有用。以上是关于在 .net 核心 Web API 中自动添加策略属性的主要内容,如果未能解决你的问题,请参考以下文章
转如何在Web项目中给没有添加API核心组件添加APIController的帮助页HelpPage
无法在 asp.net 核心中为身份服务器 4 启用 CORS
添加 Authorize 属性时 Web api 核心返回 404