Автоматическое добавление атрибута политики в основной веб-API .net - PullRequest
0 голосов
/ 05 ноября 2018

Я использую .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 Ответ

0 голосов
/ 05 ноября 2018

Для этого вы можете использовать пользовательское соглашение , которое позволяет настроить модель приложения . Использование соглашения позволяет автоматически добавлять фильтры к каждому действию в вашем проекте, используя либо глобальную регистрацию указанного соглашения, либо применяя его с помощью атрибута к действию и т. Д.

Вот пример реализации пользовательского соглашения для ваших целей:

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

В этом примере мы реализуем IActionModelConvention, который определяет метод Apply, который вызывается средой MVC при инициализации. В приведенной выше реализации мы просто добавляем AuthorizeFilter к модели, которая использует имя действия в качестве имени политики.

Чтобы зарегистрировать соглашение, добавьте его через MvcOptions в Startup.ConfigureServices. e.g.:

serices.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 - вместо этого его можно добавить как атрибут. e.g.:

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

Наконец, если вы хотите применить соглашение к контроллерам, но делаете это с помощью кода, вы можете зарегистрировать соглашение в Startup.ConfigureServices (как в подходе SomeActionModelConvention), а затем настроить реализацию Apply, чтобы добавить только фильтр в соответствии с вашей собственной логикой. Я не буду вдаваться в подробности этого, так как уже достаточно долго.

...