Как отправлять пользовательские заголовки с запросами в 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
Вы также можете добавить определение безопасности с типом 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: []
},
},
}