Как отправлять пользовательские заголовки с запросами в Swagger UI?

У меня есть некоторые конечные точки в API - /user/login, /products,

В Swagger UI я публикую email а также password в /user/login и в ответ я получаю token строка.

Затем я могу скопировать токен из ответа и использовать его как Authorization значение заголовка в запросах ко всем URL, если оно присутствует, и /products В качестве примера.

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

15 ответов

Решение

Вы можете добавить параметр заголовка к вашему запросу, и Swagger-UI покажет его в виде редактируемого текстового поля:

swagger: "2.0"
info:
  version: 1.0.0
  title: TaxBlaster
host: taxblaster.com
basePath: /api
schemes:
- http

paths:

  /taxFilings/{id}:

    get:
      parameters:
      - name: id
        in: path
        description: ID of the requested TaxFiling
        required: true
        type: string
      - name: auth
        in: header
        description: an authorization header
        required: true
        type: string
      responses:
        200:
          description: Successful response, with a representation of the Tax Filing.
          schema:
            $ref: "#/definitions/TaxFilingObject"
        404:
          description: The requested tax filing was not found.

definitions:
  TaxFilingObject:
    type: object
    description: An individual Tax Filing record.
    properties:
      filingID:
        type: string
      year:
        type: string
      period:
        type: integer
      currency:
        type: string
      taxpayer:
        type: object

Swagger-UI с текстовым полем auth param

Вы также можете добавить определение безопасности с типом apiKey:

swagger: "2.0"
info:
  version: 1.0.0
  title: TaxBlaster
host: taxblaster.com
basePath: /api
schemes:
- http

securityDefinitions:
  api_key:
    type: apiKey
    name: api_key
    in: header
    description: Requests should pass an api_key header.

security: 
 - api_key: []

paths:

  /taxFilings/{id}:

    get:
      parameters:
      - name: id
        in: path
        description: ID of the requested TaxFiling
        required: true
        type: string

      responses:
        200:
          description: Successful response, with a representation of the Tax Filing.
          schema:
            $ref: "#/definitions/TaxFilingObject"
        404:
          description: The requested tax filing was not found.

definitions:
  TaxFilingObject:
    type: object
    description: An individual Tax Filing record.
    properties:
      filingID:
        type: string
      year:
        type: string
      period:
        type: integer
      currency:
        type: string
      taxpayer:
        type: object

securityDefinitions Объект определяет схемы безопасности.

security Объект (называемый "требования безопасности" в Swagger–OpenAPI), применяет схему безопасности к заданному контексту. В нашем случае мы применяем его ко всему API, объявив требование безопасности на высшем уровне. При желании мы можем переопределить его в пределах отдельных элементов пути и / или методов.

Это был бы предпочтительный способ указать вашу схему безопасности; и он заменяет параметр заголовка из первого примера. К сожалению, в Swagger-UI нет текстового поля для управления этим параметром, по крайней мере, в моем тестировании.

В ASP.net WebApi самый простой способ передать заголовок в Swagger UI - это реализовать метод Apply(...) в интерфейсе IOperationFilter.

Добавьте это к вашему проекту:

public class AddRequiredHeaderParameter : IOperationFilter
{
    public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
    {
        if (operation.parameters == null)
            operation.parameters = new List<Parameter>();

        operation.parameters.Add(new Parameter
        {
            name = "MyHeaderField",
            @in = "header",
            type = "string",
            description = "My header field",
            required = true
        });
    }
}

На SwaggerConfig.cs зарегистрируйте фильтр сверху, используя c.OperationFilter():

    public static void Register()
    {
        var thisAssembly = typeof(SwaggerConfig).Assembly;

        GlobalConfiguration.Configuration 
            .EnableSwagger(c =>
            {
                c.SingleApiVersion("v1", "YourProjectName");
                c.IgnoreObsoleteActions();
                c.UseFullTypeNameInSchemaIds();
                c.DescribeAllEnumsAsStrings();
                c.IncludeXmlComments(GetXmlCommentsPath());
                c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());


                c.OperationFilter<AddRequiredHeaderParameter>(); // Add this here
            })
            .EnableSwaggerUi(c =>
            {
                c.DocExpansion(DocExpansion.List);
            });
    }

В ASP.NET Core 2 Web APIиспользуя пакет 2.1.0 Swashbuckle.AspNetCore, реализуем IDocumentFilter:

SwaggerSecurityRequirementsDocumentFilter.cs

using System.Collections.Generic;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace api.infrastructure.filters
{
    public class SwaggerSecurityRequirementsDocumentFilter : IDocumentFilter
    {
        public void Apply(SwaggerDocument document, DocumentFilterContext context)
        {
            document.Security = new List<IDictionary<string, IEnumerable<string>>>()
            {
                new Dictionary<string, IEnumerable<string>>()
                {
                    { "Bearer", new string[]{ } },
                    { "Basic", new string[]{ } },
                }
            };
        }
    }
}

В Startup.cs настройте определение безопасности и зарегистрируйте пользовательский фильтр:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSwaggerGen(c =>
    {
        // c.SwaggerDoc(.....

        c.AddSecurityDefinition("Bearer", new ApiKeyScheme()
        {
            Description = "Authorization header using the Bearer scheme",
            Name = "Authorization",
            In = "header"
        });

        c.DocumentFilter<SwaggerSecurityRequirementsDocumentFilter>();
    });
}

В интерфейсе Swagger нажмите кнопку "Авторизовать" и установите значение для токена.

Окно для установки значения

Результат:

curl -X GET "http://localhost:5000/api/tenants" -H "accept: text/plain" -H "Authorization: Bearer ABCD123456"

Также можно использовать атрибут [FromHeader] для параметров веб-методов (или свойств в классе Model), которые следует отправлять в пользовательских заголовках. Что-то вроде этого:

[HttpGet]
public ActionResult Products([FromHeader(Name = "User-Identity")]string userIdentity)

По крайней мере, он отлично работает для ASP.NET Core 2.1 и Swashbuckle.AspNetCore 2.5.0.

Вот как я этого добился в .NET 6

      public class AddCustomHeaderParameter 
    : IOperationFilter
{
    public void Apply(
        OpenApiOperation operation, 
        OperationFilterContext context)
    {
        if (operation.Parameters is null)
        {
            operation.Parameters = new List<OpenApiParameter>();
        }

        operation.Parameters.Add(new OpenApiParameter
        {
            Name = "Custom Header",
            In = ParameterLocation.Header,
            Description = "Custom Header description",
            Required = true,
        });
    }
}

И наконец

      services.AddSwaggerGen(c =>
        {
            c.OperationFilter<AddCustomHeaderParameter>();
        });

Вот более простой ответ для комбо ASP.NET Core Web Api/Swashbuckle, который не требует регистрации каких-либо пользовательских фильтров. Третий раз это очарование, вы знаете:).

Добавление приведенного ниже кода в конфигурацию Swagger приведет к появлению кнопки "Авторизовать", которая позволит вам ввести маркер канала-носителя для отправки всех запросов. Не забудьте ввести этот токен как Bearer <your token here> когда спросили

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

services.AddSwaggerGen(c =>
{
    //...

    c.AddSecurityDefinition("Bearer", new ApiKeyScheme()
    {
        Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
        Name = "Authorization",
        In = "header",
        Type = "apiKey"
    });

    c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
    {
        { "Bearer", new string[] { } }
    });

    //...
}


Через эту ветку.

Просто обновите это для веб-API Asp.Net Core 6 и Swashbuckle.AspNetCore 6.4.0. Это было на удивление легко. В моем случае заголовок требуется для всех методов действия, поэтому у меня Required true.

Во-первых, создайте Swashbuckle.AspNetCore.SwaggerGen.IOperationFilter:

      public class IMyCustomFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        if (operation.Parameters == null)
            operation.Parameters = new List<OpenApiParameter>();

        operation.Parameters.Add(new OpenApiParameter()
        {
             Name= "MyCustomHeader",
             In=ParameterLocation.Header,
             Required=true
        });
    }
}

Во-вторых, скажите Swagger использовать его при настройке сервисов:

      builder.Services.AddSwaggerGen(config =>
                {
                    //this causes Swagger to add an input so you can to add the value to header when you are executing an api method.
                    config.OperationFilter<IMyCustomFilter>();
                });

В-третьих, вызовите Swagger, как обычно:

              var app = builder.Build();

        if (app.Environment.IsDevelopment())
        {
            app.UseSwagger();
            app.UseSwaggerUI();
        }

Если вы работаете с Nest.js, этого можно добиться добавлением addBearerAuth()при настройке чванства (вероятно, в main.ts).

      ...........

  const config = new DocumentBuilder()
    .setTitle('Your title')
    .setDescription('Your description')
    .setVersion('1.0')
    .addBearerAuth()   // Add here
    .build();

  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('api', app, document);

...........

С этим добавлением мы можем передать токен Bearer из пользовательского интерфейса Swagger как:

PS: Вы должны использовать Authguard в соответствующих контроллерах для защиты ваших маршрутов.

Для тех, кто использует NSwag и нужен собственный заголовок:

app.UseSwaggerUi3(typeof(Startup).GetTypeInfo().Assembly, settings =>
      {
          settings.GeneratorSettings.IsAspNetCore = true;
          settings.GeneratorSettings.OperationProcessors.Add(new OperationSecurityScopeProcessor("custom-auth"));

          settings.GeneratorSettings.DocumentProcessors.Add(
              new SecurityDefinitionAppender("custom-auth", new SwaggerSecurityScheme
                {
                    Type = SwaggerSecuritySchemeType.ApiKey,
                    Name = "header-name",
                    Description = "header description",
                    In = SwaggerSecurityApiKeyLocation.Header
                }));
        });            
    }

Swagger UI будет включать кнопку авторизации.

Обновление для OpenAPI 3, библиотека Swashbuckle.AspNetCore. Правильный образец кода предоставлен этим источником: https://codeburst.io/api-security-in-swagger-f2afff82fb8e

Для использования с JWT Bearer правильный код:

      services.AddSwaggerGen(c =>
{
    // configure SwaggerDoc and others

    // add JWT Authentication
    var securityScheme = new OpenApiSecurityScheme
    {
        Name = "JWT Authentication",
        Description = "Enter JWT Bearer token **_only_**",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.Http,
        Scheme = "bearer", // must be lower case
        BearerFormat = "JWT",
        Reference = new OpenApiReference
        {
            Id = JwtBearerDefaults.AuthenticationScheme,
            Type = ReferenceType.SecurityScheme
        }
    };
    c.AddSecurityDefinition(securityScheme.Reference.Id, securityScheme);
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {securityScheme, new string[] { }}
    });
}

Я видел одну статью с аналогичным кодом для OpenAPI 2 и потерял много часов, потому что в этом примере отсутствует определение ссылки. Это привело к тому, что Swashbuckle сгенерировал неверные определения и не включил заголовок авторизации. Поэтому внимательно проверьте версию OpenAPI, которую вы используете.

Я попал сюда, потому что я пытался условно добавить параметры заголовка в Swagger UI, основываясь на моем собственном [Authentication] атрибут, который я добавил в свой метод API. После намека на то, что @Corcus указан в комментарии, я смог найти свое решение, и, надеюсь, оно поможет другим.

Используя Reflection, он проверяет, вложен ли метод в apiDescription имеет нужный атрибут (в моем случае MyApiKeyAuthenticationAttribute). Если это так, я могу добавить желаемые параметры заголовка.

public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription) {
    if (operation.parameters == null)
        operation.parameters = new List<Parameter>();


    var attributes = ((System.Web.Http.Controllers.ReflectedHttpActionDescriptor)
        ((apiDescription.ActionDescriptor).ActionBinding.ActionDescriptor)).MethodInfo
        .GetCustomAttributes(false);
    if(attributes != null && attributes.Any()) {
        if(attributes.Where(x => x.GetType() 
            == typeof(MyApiKeyAuthenticationAttribute)).Any()) {

            operation.parameters.Add(new Parameter {
                name = "MyApiKey",
                @in = "header",
                type = "string",
                description = "My API Key",
                required = true
            });
            operation.parameters.Add(new Parameter {
                name = "EID",
                @in = "header",
                type = "string",
                description = "Employee ID",
                required = true
            });
        }
    }


}

Предположим, вы создаете документацию непосредственно из класса контроллера вместо использования файла спецификации yaml OpenAPI3 или Swagger2. В этом случае методы конечной точки вашего контроллера также должны включать параметры заголовков, которые вы хотите видеть в swagger-ui. Параметр(ы) заголовка в методах конечной точки вашего контроллера автоматически получит значения заголовка, переданные в запросе. Он также заставит swagger-ui отображать вводимые данные в виде редактируемого текстового поля.

Например, предположим, что у вас есть конечная точка контроллера, определенная как:

      public ResponseEntity taxFilings(@PathVariable(value = "id") String id) {
   //some codes to do
}

Рефакторинг определения метода следующим образом:

      public ResponseEntity taxFilings(@PathVariable(value = "id") String id, @RequestHeader(value = "auth") String auth) {
   //some codes to do
}

Реализация метода конечной точки не обязательно должна использовать параметр заголовка; заголовок, переданный в HTTP-запросе, по-прежнему будет полезен везде, где он вам понадобится, например фильтры и классы безопасности. Единственная причина, по которой он был передан в параметре метода конечных точек, заключается в том, чтобы сделать его видимым в swagger-ui, поскольку swagger смотрит на классы контроллера при определении и использовании конечных точек.

Пример Golang/go-swagger: https://github.com/go-swagger/go-swagger/issues/1416

// swagger:parameters opid
type XRequestIdHeader struct {
    // in: header
    // required: true
    XRequestId string `json:"X-Request-Id"`
}

...
    // swagger:operation POST /endpoint/ opid
    // Parameters:
    // - $ref: #/parameters/XRequestIDHeader

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: это решение не использует заголовок.

Если кто-то ищет ленивый способ (также в WebApi), я бы предложил:

public YourResult Authorize([FromBody]BasicAuthCredentials credentials)

Вы не получаете от заголовка, но по крайней мере у вас есть легкая альтернатива. Вы всегда можете проверить объект на ноль и механизм возврата к заголовку.

В Feathers Swagger, чтобы отобразить кнопку авторизации в правом верхнем углу в этом случае для BearerAuth, ваше объявление конфигурации должно быть выполнено следующим образом:

      {
  ...config, // other config parameters
  specs: {
    info: {
      title: 'My API',
      description: 'My API Documentation',
      version: '2.0',
    },
    components: {
      securityDefinitions: {
        BasicAuth: {
          type: 'basic'
        },
        BearerAuth: {
          type: "http",
          scheme: "bearer",
          bearerFormat: "JWT"
        }
      },
    },
    security: {
      BearerAuth: []
    },
  },
}

Результат

Другие вопросы по тегам