如何在 Swagger UI 中发送带有请求的自定义 headers?
How to send custom headers with requests in Swagger UI?
我在 API 中有一些端点 - /user/login
、/products
。
在 Swagger UI 我 post email
和 password
到 /user/login
作为响应我收到一个 token
字符串。
然后,我可以从响应中复制令牌,并希望将其用作所有 url 请求中的 Authorization
header 值(如果它存在),并将 /products
作为例如。
我应该在 Swagger UI 页面的某处手动创建文本输入,然后将令牌放在那里并以某种方式注入请求,还是有工具可以更好地管理它?
您可以在您的请求中添加一个header参数,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
object 定义了安全方案。
security
object(在 Swagger–OpenAPI 中称为 "security requirements"),将安全方案应用于给定的上下文。在我们的例子中,我们通过将安全要求声明为顶级来将其应用于整个 API。我们可以选择在单个路径项 and/or 方法中覆盖它。
这是指定安全方案的首选方式;它替换了第一个示例中的 header 参数。不幸的是,Swagger-UI 没有提供文本框来控制这个参数,至少在我目前的测试中是这样。
在 ASP.NET Web API 中,在 Swagger UI 上 pass-in 一个 header 的最简单方法是实现 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<T>()
:
从上面注册过滤器
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);
});
}
我最终来到这里是因为我试图根据我自己添加到 API 方法的 [Authentication]
属性,在 Swagger UI 中有条件地添加 header 参数.按照@Corcus 在评论中列出的提示,我能够得出我的解决方案,希望它能帮助其他人。
使用反射检查 apiDescription
中嵌套的方法是否具有所需的属性(在我的例子中为 MyApiKeyAuthenticationAttribute)。如果是这样,我可以附加我想要的 header 参数。
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
});
}
}
}
在ASP.NET Core 2 Web API
中,使用Swashbuckle.AspNetCore包2.1.0,实现一个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 UI 中,单击“授权”按钮并设置令牌值。
结果:
curl -X GET "http://localhost:5000/api/tenants" -H "accept: text/plain" -H "Authorization: Bearer ABCD123456"
对于那些使用 NSwag 并且需要自定义 header 的人:
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 将包含一个 Authorize 按钮。
免责声明:此解决方案不是使用Header。
如果有人正在寻找 lazy-lazy 方式(也在 WebApi 中),我建议:
public YourResult Authorize([FromBody]BasicAuthCredentials credentials)
你不是从 header 那里得到的,但至少你有一个简单的选择。
您始终可以检查 object 是否为 null 并回退到 header 机制。
也可以将属性 [FromHeader] 用于 Web 方法参数(或模型 class 中的属性),这些参数应在自定义 headers 中发送。像这样:
[HttpGet]
public ActionResult Products([FromHeader(Name = "User-Identity")] string userIdentity)
至少它在 ASP.NET Core 2.1 和 Swashbuckle.AspNetCore 2.5.0 上工作正常。
这是 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[] { } }
});
//...
}
通过this thread.
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
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 生成了不正确的定义并且没有包含授权 header。因此请仔细检查您使用的 OpenAPI 版本。
这就是我在 .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>();
});
如果您正在使用 Nest.js
,可以通过在设置 swagger 时添加 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);
...........
加上这个,我们可以从 Swagger UI 传入 Bearer 令牌,如下所示:
PS: 你必须在各自的控制器中使用 Authguard 来保护你的路由。
我在 API 中有一些端点 - /user/login
、/products
。
在 Swagger UI 我 post email
和 password
到 /user/login
作为响应我收到一个 token
字符串。
然后,我可以从响应中复制令牌,并希望将其用作所有 url 请求中的 Authorization
header 值(如果它存在),并将 /products
作为例如。
我应该在 Swagger UI 页面的某处手动创建文本输入,然后将令牌放在那里并以某种方式注入请求,还是有工具可以更好地管理它?
您可以在您的请求中添加一个header参数,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
object 定义了安全方案。
security
object(在 Swagger–OpenAPI 中称为 "security requirements"),将安全方案应用于给定的上下文。在我们的例子中,我们通过将安全要求声明为顶级来将其应用于整个 API。我们可以选择在单个路径项 and/or 方法中覆盖它。
这是指定安全方案的首选方式;它替换了第一个示例中的 header 参数。不幸的是,Swagger-UI 没有提供文本框来控制这个参数,至少在我目前的测试中是这样。
在 ASP.NET Web API 中,在 Swagger UI 上 pass-in 一个 header 的最简单方法是实现 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<T>()
:
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);
});
}
我最终来到这里是因为我试图根据我自己添加到 API 方法的 [Authentication]
属性,在 Swagger UI 中有条件地添加 header 参数.按照@Corcus 在评论中列出的提示,我能够得出我的解决方案,希望它能帮助其他人。
使用反射检查 apiDescription
中嵌套的方法是否具有所需的属性(在我的例子中为 MyApiKeyAuthenticationAttribute)。如果是这样,我可以附加我想要的 header 参数。
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
});
}
}
}
在ASP.NET Core 2 Web API
中,使用Swashbuckle.AspNetCore包2.1.0,实现一个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 UI 中,单击“授权”按钮并设置令牌值。
结果:
curl -X GET "http://localhost:5000/api/tenants" -H "accept: text/plain" -H "Authorization: Bearer ABCD123456"
对于那些使用 NSwag 并且需要自定义 header 的人:
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 将包含一个 Authorize 按钮。
免责声明:此解决方案不是使用Header。
如果有人正在寻找 lazy-lazy 方式(也在 WebApi 中),我建议:
public YourResult Authorize([FromBody]BasicAuthCredentials credentials)
你不是从 header 那里得到的,但至少你有一个简单的选择。 您始终可以检查 object 是否为 null 并回退到 header 机制。
也可以将属性 [FromHeader] 用于 Web 方法参数(或模型 class 中的属性),这些参数应在自定义 headers 中发送。像这样:
[HttpGet]
public ActionResult Products([FromHeader(Name = "User-Identity")] string userIdentity)
至少它在 ASP.NET Core 2.1 和 Swashbuckle.AspNetCore 2.5.0 上工作正常。
这是 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[] { } }
});
//...
}
通过this thread.
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
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 生成了不正确的定义并且没有包含授权 header。因此请仔细检查您使用的 OpenAPI 版本。
这就是我在 .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>();
});
如果您正在使用 Nest.js
,可以通过在设置 swagger 时添加 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);
...........
加上这个,我们可以从 Swagger UI 传入 Bearer 令牌,如下所示:
PS: 你必须在各自的控制器中使用 Authguard 来保护你的路由。