Использование фильтров работы OpenAPI для добавления требований безопасности к конечным точкам контроллера, требующим аутентификации - PullRequest
1 голос
/ 15 марта 2020

Я пытаюсь улучшить определение openapi своих проектов, добавив требования безопасности к конечным точкам, требующим аутентификации.

Конечной точке требуется аутентификация, если это метод класса с декоратором [Authorize], и ему не хватает [AllowAnonymous] decorator.

Я пытаюсь использовать IOperationFilter для добавления требований безопасности, основанных на этом, но я борюсь с дескрипторами фильтров - я не могу найти никакой документации о том, как они работают вообще.

Это мой текущий фильтр, основанный на другом потоке StackOverflow:

using Microsoft.AspNetCore.Http; 
using Microsoft.AspNetCore.Mvc.Authorization; 
using Microsoft.OpenApi.Models;

using Swashbuckle.AspNetCore.Swagger; 
using Swashbuckle.AspNetCore.SwaggerGen; 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Threading.Tasks;

namespace OpenData.Filters {
    public class AddAuthHeaderOperationFilter : IOperationFilter
    {
        private readonly IHttpContextAccessor httpContextAccessor;

        public AddAuthHeaderOperationFilter(IHttpContextAccessor httpContextAccessor)
        {
            this.httpContextAccessor = httpContextAccessor;
        }

        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            var filterDescriptor = context.ApiDescription.ActionDescriptor.FilterDescriptors;
            var isAuthorized = filterDescriptor.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
            var allowAnonymous = filterDescriptor.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter);

            if (/*isAuthorized && */!allowAnonymous)
            {
                operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });
                operation.Responses.Add("403", new OpenApiResponse { Description = "Forbidden" });
                //Add JWT bearer type
                operation.Security.Add(new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id = "Bearer"
                            },
                            Scheme = "Bearer",
                            Name = "Bearer",
                            In = ParameterLocation.Header,

                        },
                        new List<string>()
                    }
                });
            }
        }
    }
}

Моя проблема в части filterDescriptor. Как я могу использовать это, чтобы определить, является ли то, что я сейчас применяю, методом класса с [Authorize] декоратором, если он есть, если у него есть [AllowAnonymous] декоратор? Возможно, я тоже неправильно использую термины, это метод, который я хочу обнаружить:

    [Authorize]
    [Route("/api/[controller]")]
    public class CommentController : Controller
    {

        [AllowAnonymous]
        [HttpGet("metadata/{metadataUuid}")]
        public async Task<IActionResult> GetCommentsForMetadataAsync(Guid metadataUuid)
        {
            // ...
        }

Изучение этого затруднительно, и, похоже, нет доступной документации по этому API на в Интернете, и я не смог найти ни одного примера для этой версии dotnetcore / swagger.

Мои версии:

  • .netcore 3.1
  • Swashbuckle.AspNetCore 5.0.0

1 Ответ

1 голос
/ 16 марта 2020

метод класса с декоратором [Authorize], если он (действие) имеет декоратор [AllowAnonymous]? Возможно, я также неправильно использую термины

Чтобы выполнить вышеуказанное требование, вы можете попробовать следующий фрагмент кода:

public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
    var authAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true)
        .Union(context.MethodInfo.GetCustomAttributes(true))
        .OfType<AuthorizeAttribute>();

    var allowAnonymousAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true)
        .Union(context.MethodInfo.GetCustomAttributes(true))
        .OfType<AllowAnonymousAttribute>();


    if (authAttributes.Any() && !allowAnonymousAttributes.Any())
    {
        operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });
        operation.Responses.Add("403", new OpenApiResponse { Description = "Forbidden" });
    }
        //...

}

Для получения дополнительной информации о рабочих фильтрах, пожалуйста, проверьте эту документацию:

https://github.com/domaindrivendev/Swashbuckle.AspNetCore#operation -фильтры

...