Kłódki Swashbuckle Swagger UI z OAS3 [duplikat]

Nov 25 2020

Mam interfejs API sieci Web ASP.Net Core Rest udokumentowany za pomocą generacji Swagger Swashbuckles (.net v5 i Swashbuckle.AspNetCore v5.6.3). Generuje dokumentację Swaggera i interfejs użytkownika z obsługą OAS3.

Również mój interfejs API używa tokenów okaziciela JWT. Więc dodałem ten kod do konfiguracji swaggera:

options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
    In = ParameterLocation.Header,
    Name = "Authorization",
    Type = SecuritySchemeType.ApiKey,
    Description = "Put `bearer` keyword in front of token"
});

options.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
    {
        new OpenApiSecurityScheme()
        {
            Reference = new OpenApiReference()
            {
                Id = "Bearer",
                Type = ReferenceType.SecurityScheme
            }
        },
        Array.Empty<string>()
    }
});

I zgodnie z oczekiwaniami dodał możliwość autoryzacji do interfejsu użytkownika Swagger:

Ale zauważyłem też kilka kłódek przy każdym żądaniu HTTP. Są odblokowane przed autoryzacją:

A po autoryzacji blokują:

Jak mogę sprawić, by te kłódki sygnalizowały, czy autoryzacja jest wymagana, czy nie (myślę, że widziałem gdzieś te same kłódki, które to robią i wydaje im się całkiem naturalne, że robią to również)?

Próbowałem już czegoś takiego, ale nie zadziałało (nagłówki żądań nie zawierały już tokenu jwt):

options.OperationFilter<SecurityRequirementsOperationFilter>();

Dowiedziałem się, że problem polega na tym, że mój Swagger używa OAS3 i jest SecurityRequirementsOperationFilterzależny od OAS2. Próbowałem szukać alternatyw, ale wygląda na to, że nie ma podobnych narzędzi dla OAS3.

Co powinienem zrobić? Czy powinienem zapomnieć o tej funkcji? Ale to wygląda na jedyny cel tych zamków. Czy są jakieś sposoby, aby mieć tę funkcję i pozostać przy OAS3 (również nie jestem pewien, czy naprawdę potrzebuję obsługi OAS3 tak bardzo).

Odpowiedzi

catman0745 Nov 25 2020 at 13:38

Po kilku badaniach znalazłem odpowiedź tutaj: https://stackoverflow.com/a/61365691/13851956.

Więc kod to:

options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
    Description = "No need to put the `bearer` keyword in front of token",
    Type = SecuritySchemeType.Http,
    Scheme = "bearer",
    BearerFormat = "JWT"
});
options.OperationFilter<AuthorizationOperationFilter>();
public class AuthorizationOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        var actionMetadata = context.ApiDescription.ActionDescriptor.EndpointMetadata;
        var isAuthorized = actionMetadata.Any(metadataItem => metadataItem is AuthorizeAttribute);
        var allowAnonymous = actionMetadata.Any(metadataItem => metadataItem is AllowAnonymousAttribute);
        if (!isAuthorized || allowAnonymous)
        {
            return;
        }
        
        operation.Parameters ??= new List<OpenApiParameter>();
        operation.Security = new List<OpenApiSecurityRequirement>
        {
            new OpenApiSecurityRequirement
            {
                {
                    new OpenApiSecurityScheme
                    {
                        Reference = new OpenApiReference
                        {
                            Id = "Bearer",
                            Type = ReferenceType.SecurityScheme
                        }
                    },
                    Array.Empty<string>()
                }
            }
        };
    }
}

W rezultacie kłódki pojawiają się tylko obok działań oznaczonych [Authorize] i nie oznaczonych atrybutami [AllowAnonymous]: