ASP Net Core 2.2 add locker icon only to methods that require authorization - Swagger UI

后端 未结 2 1634
抹茶落季
抹茶落季 2021-01-12 17:12

Versions:

  • ASP Net Core Web API - 2.2
  • Swashbuckle.AspNetCore - 4.0.1

What I currently have?

I have implemented swagg

相关标签:
2条回答
  • 2021-01-12 17:17

    For Swashbuckle 5.0.0 and later AddAuthHeaderOperationFilter from @G.Dimov's answer changes to following (with some additional style edits):

    public class AddAuthHeaderOperationFilter : IOperationFilter
    {
        private readonly IHttpContextAccessor httpContextAccessor;
    
        public AddAuthHeaderOperationFilter(IHttpContextAccessor httpContextAccessor)
        {
            this.httpContextAccessor = httpContextAccessor;
        }
    
        public void Apply(Operation 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)
            {
                if (operation.Parameters == null)
                    operation.Parameters = new List<IParameter>();
    
                operation.Parameters.Add(new NonBodyParameter
                {
                    Name = "Authorization",
                    In = "header",
                    Description = "JWT access token",
                    Required = true,
                    Type = "string"
                });
    
                operation.Responses.Add("401", new Response { Description = "Unauthorized" });
                operation.Responses.Add("403", new Response { Description = "Forbidden" });
    
                operation.Security = new List<IDictionary<string, IEnumerable<string>>>();
    
                //Add JWT bearer type
                operation.Security.Add(new Dictionary<string, IEnumerable<string>>
                {
                    { "Bearer", new string[] { } }
                });
            }
        }
    }
    

    EDIT

    Swagger UI refuses to send the Authorization header if it is defined as a parameter. So probably better option will be to create a security definition in the SwaggerGen service configuration (usually in Startup.ConfigureServices):

    public void ConfigureServices(IServiceCollection services)
    {
        // Service configuration
        services.AddSwaggerGen(c =>
        {
            // Configure Swagger
            // "Bearer" is the name for this definition. Any other name could be used
            c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                {
                    Description = "Use bearer token to authorize",
                    Type = SecuritySchemeType.Http,
                    Scheme = "bearer",
                    BearerFormat = "JWT"
                });
        }
    }
    

    And then add a security requirement with a reference to a definition to the operation:

    public class AddAuthorizationHeaderOperationHeader : 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;
            }
            if (operation.Parameters == null)
                operation.Parameters = new List<OpenApiParameter>();
    
            operation.Security = new List<OpenApiSecurityRequirement>();
    
            //Add JWT bearer type
            operation.Security.Add(new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {                            
                            Reference = new OpenApiReference
                            {                               
                                Type = ReferenceType.SecurityScheme,
                                // Definition name. 
                                // Should exactly match the one given in the service configuration
                                Id = "Bearer"
                            }
                        }, new string[0]
                    }
                }
            );
        }
    }
    
    0 讨论(0)
  • 2021-01-12 17:36

    Since it went more than a month since I asked this one. Here is how I did it.

    I deleted the following code from Startup.cs:

    c.AddSecurityDefinition("Bearer", new ApiKeyScheme
    {
        In = "header",
        Description = "Please enter into field the word 'Bearer' following by space and your JWT token",
        Name = "Authorization",
        Type = "apiKey"
    });
    c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
    {
        { "Bearer", Enumerable.Empty<string>() },
    });
    

    And I added the following one:

    c.OperationFilter<AddAuthHeaderOperationFilter>();
    

    And of course the AddAuthHeaderOperationFilter.cs:

        public class AddAuthHeaderOperationFilter : IOperationFilter
        {
            private readonly IHttpContextAccessor httpContextAccessor;
    
            public AddAuthHeaderOperationFilter(IHttpContextAccessor httpContextAccessor)
            {
                this.httpContextAccessor = httpContextAccessor;
            }
    
            public void Apply(Operation 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)
                {
                    if (operation.Parameters == null)
                        operation.Parameters = new List<IParameter>();
    
                    operation.Parameters.Add(new NonBodyParameter
                    {
                        Name = "Authorization",
                        In = "header",
                        Description = "JWT access token",
                        Required = true,
                        Type = "string",
                        //Default = $"Bearer {token}"
                    });
    
                    operation.Responses.Add("401", new Response { Description = "Unauthorized" });
                    operation.Responses.Add("403", new Response { Description = "Forbidden" });
    
                    operation.Security = new List<IDictionary<string, IEnumerable<string>>>();
    
                    //Add JWT bearer type
                    operation.Security.Add(new Dictionary<string, IEnumerable<string>>
                    {
                        { "Bearer", new string[] { } }
                    });
                }
            }
        }
    

    Shortly, this OperationFilter class only adds the locker icon to methods that require Authorization. The locker is always Opened though. So not the perfect solution, but for now is ok.

    Here is how it looks:

    Note: So if you want to test the API, you first get a token and then fill it where needed.

    0 讨论(0)
提交回复
热议问题