【发布时间】:2017-05-20 11:22:51
【问题描述】:
我搜索了添加请求标头参数的可能方法,该参数将自动添加到我的web-api 中的每个方法中,但我找不到明确的方法。
在搜索时,我发现 OperationFilter() 方法必须对其进行处理。
【问题讨论】:
-
想知道这是否可以通过 Swagger UI 完成?
标签: c# asp.net-web-api swagger swagger-ui
我搜索了添加请求标头参数的可能方法,该参数将自动添加到我的web-api 中的每个方法中,但我找不到明确的方法。
在搜索时,我发现 OperationFilter() 方法必须对其进行处理。
【问题讨论】:
标签: c# asp.net-web-api swagger swagger-ui
是的,您可以通过从 IOperationFilter 继承来做到这一点
你可以在 GitHub 上找到答案:AddRequiredHeaderParameter
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
public class AddRequiredHeaderParameter : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
if (operation.Parameters == null)
operation.Parameters = new List<IParameter>();
operation.Parameters.Add(new NonBodyParameter
{
Name = "X-User-Token",
In = "header",
Type = "string",
Required = false
});
}
}
然后您转到您的SwaggerConfig.cs 文件并在AddSwaggerGen 部分添加以下内容:
c.OperationFilter<AddRequiredHeaderParameter>();
重建并享受。
【讨论】:
您也可能有一个基本模型类并使用属性 [FromHeader] 来获取应在自定义标头中发送的属性。像这样的东西:
public class AuthenticatedRequest
{
[FromHeader(Name = "User-Identity")]
public string UserIdentity { get; set; }
}
至少它适用于 ASP.NET Core 2.1 和 Swashbuckle.AspNetCore 2.5.0。
【讨论】:
用户“G T”写的是正确的,但它不适用于 Swagger 5。我们有一些新的变化:
发件人:Operation 至:OpenApiOperation
从:IParameter 到:OpenApiParameter
从:NonBodyParameter 到:OpenApiParameter,最重要的是……
从:Type = "string" 到:Schema = new OpenApiSchema { Type = "String" }
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace MyAPI
{
public class AuthorizationHeaderParameterOperationFilter: IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var filterPipeline = context.ApiDescription.ActionDescriptor.FilterDescriptors;
var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
var allowAnonymous = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter);
if (isAuthorized && !allowAnonymous)
{
if (operation.Parameters == null)
operation.Parameters = new List<OpenApiParameter>();
operation.Parameters.Add(new OpenApiParameter
{
Name = "Authorization",
In = ParameterLocation.Header,
Description = "access token",
Required = true,
Schema = new OpenApiSchema
{
Type = "string",
Default = new OpenApiString("Bearer ")
}
});
}
}
}
}
并且在 Startup => ConfigureServices => services.AddSwaggerGen()
c.OperationFilter<AuthorizationHeaderParameterOperationFilter>();
【讨论】:
Type = "String" 更改为"Type = "string" 让SwaggerUI 再次使用required = true 属性!
对于 Asp .Net MVC 5,您可以使用。
以下需要在 Swagger Config 文件中完成。
private class AddAuthorizationHeaderParameter: IOperationFilter // as a nested class in script config file.
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
if (operation.parameters == null)
operation.parameters = new List<Parameter>();
operation.parameters.Add(new Parameter
{
name = "Authorization",
@in = "header",
type = "string",
required = true
});
}
}
c.OperationFilter<AddAuthorizationHeaderParameter>(); // finally add this line in .EnableSwagger
您还可以为 Swagger 中的标头实现添加任何标头。
【讨论】:
我已经稍微改进了尊敬的 Wille Esteche 的回答。 如果您不想将标头应用于所有方法,而仅应用于您选择的控制器方法,则可以使用属性。
[HttpPost]
[Route(nameof(Auth))]
[SwaggerHeader(Constants.HeaderDomainSid, "Encrypted User.Sid got from client", "abc123", true)]
public ActionResult<string> Auth([FromHeader(Name = Constants.HeaderDomainSid)] string headerDomainSid = null)
{ .....
属性类:
public class SwaggerHeaderAttribute : Attribute
{
public string HeaderName { get; }
public string Description { get; }
public string DefaultValue { get; }
public bool IsRequired { get; }
public SwaggerHeaderAttribute(string headerName, string description = null, string defaultValue = null, bool isRequired = false)
{
HeaderName = headerName;
Description = description;
DefaultValue = defaultValue;
IsRequired = isRequired;
}
}
过滤器:
public class SwaggerHeaderFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
operation.Parameters ??= new List<OpenApiParameter>();
if (context.MethodInfo.GetCustomAttribute(typeof(SwaggerHeaderAttribute)) is SwaggerHeaderAttribute attribute)
{
var existingParam = operation.Parameters.FirstOrDefault(p =>
p.In == ParameterLocation.Header && p.Name == attribute.HeaderName);
if (existingParam != null) // remove description from [FromHeader] argument attribute
{
operation.Parameters.Remove(existingParam);
}
operation.Parameters.Add(new OpenApiParameter
{
Name = attribute.HeaderName,
In = ParameterLocation.Header,
Description = attribute.Description,
Required = attribute.IsRequired,
Schema = string.IsNullOrEmpty(attribute.DefaultValue)
? null
: new OpenApiSchema
{
Type = "String",
Default = new OpenApiString(attribute.DefaultValue)
}
});
}
}
}
【讨论】:
如果在 ASP.Net MVC5 中使用了 swagger,并且需要添加标头以从 swagger UI 中获取输入。
创建一个继承自IOperationFilter的类:
using Swashbuckle.Swagger;
using System.Collections.Generic;
using System.Web.Http.Description;
public class AddHeaderParameters : 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 = "AccountUserName",
@in = "header",
type = "string",
required = true,
//description = "Account username"
});
}
}
在SwaggerConfig.cs 内Configuration.EnableSwagger 中提供此类的参考:
c.OperationFilter<AddHeaderParameters>();
重要需要注意的是,标头名称应该与您为 API 创建的实际标头匹配。
【讨论】:
在我的情况下(.NET 5)我必须改变一些:
using System.Collections.Generic;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
public class AddRequiredHeaderParameter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.Parameters == null)
operation.Parameters = new List<OpenApiParameter>();
operation.Parameters.Add(new OpenApiParameter()
{
Name = "userNr",
In = ParameterLocation.Header,
Required = true
});
operation.Parameters.Add(new OpenApiParameter()
{
Name = "periodNo",
In = ParameterLocation.Header,
Required = true
});
}
}
在Startup.cs --> ConfigureServices --> AddSwaggerGen
添加
c.OperationFilter<AddRequiredHeaderParameter>();
【讨论】:
这适用于 Swashbucke.AspNetCore 5.6.3
创建一个新文件并将下面的代码添加到文件中
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace YourNameSpace
{
public class AuthorizationHeaderParameterOperationFilter:IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.Security == null)
operation.Security = new List<OpenApiSecurityRequirement>();
var scheme = new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "bearer" } };
operation.Security.Add(new OpenApiSecurityRequirement
{
[scheme] = new List<string>()
});
}
}
}
在您的 Startup.cs 中,将以下代码添加到 services.AddSwaggerGen() 下的 ConfigureServices 中
c.AddSecurityDefinition("bearer", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
BearerFormat = "JWT",
In = ParameterLocation.Header,
Scheme = "bearer"
});
c.OperationFilter<AuthorizationHeaderParameterOperationFilter>();
现在一切正常 更多信息请查看here
【讨论】:
不确定 .net 5.0 的 2021 年 9 月版本是否回答了这个问题,但我接受了 Rami'es 的回答并将其改编为以下内容:
namespace PartnerLicense
{
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using Walter.Web.FireWall.Reseller;
public class AddRequiredHeaderParameter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
operation.Parameters.Add(new()
{
Description = "Add your reseller ID here",
Name = HeaderKeys.ResellerId,
In = ParameterLocation.Header,
Required = true
});
}
}
}
【讨论】:
另一个定制的实现:
按照此线程的一些答案确实让我获得了授权的必填字段。但是我遇到了不同的问题。我需要修复以下问题:
Authorization 字段。为了克服上述问题,我做了以下工作:
IOperationFilter 类型过滤器以指示哪些 API 端点需要身份验证,哪些是匿名类型代码如下:
#Step-1:自定义IOperationFilter 类型过滤器:
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (context.ApiDescription.ActionDescriptor is ControllerActionDescriptor descriptor)
{
// If [AllowAnonymous] is not applied or [Authorize] or Custom Authorization filter is applied on either the endpoint or the controller
if (!context.ApiDescription.CustomAttributes().Any((a) => a is AllowAnonymousAttribute)
&& (context.ApiDescription.CustomAttributes().Any((a) => a is AuthorizeAttribute)
|| descriptor.ControllerTypeInfo.GetCustomAttribute<AuthorizeAttribute>() != null))
{
if (operation.Security == null)
operation.Security = new List<OpenApiSecurityRequirement>();
operation.Security.Add(
new OpenApiSecurityRequirement{
{
new OpenApiSecurityScheme
{
Name = "Authorization",
In = ParameterLocation.Header,
BearerFormat = "Bearer token",
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[]{ }
}
});
}
}
}
然后在 startup.cs 文件中,在 ConfigureServices 方法中添加过滤器,如下所示:
services.AddSwaggerGen(options =>
{
...
options.OperationFilter<AddRequiredHeaderParameter>();
...
...
}
执行上述操作将向需要身份验证的 API 端点添加一个图标。结果如下:
#Step-2:然后我们需要 Auth 令牌输入 UI。在您添加IOperationFilter 过滤器的startup.cs 行之后添加以下代码:
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
Name = "Authorization",
Type = SecuritySchemeType.Http,
Scheme = "Bearer",
BearerFormat = "JWT",
In = ParameterLocation.Header,
Description = "JWT Authorization header. \r\n\r\n Enter the token in the text input below.,
});
这将在 API 描述符页面的顶部为您提供一个授权按钮。单击该按钮将弹出一个窗口,您可以在其中输入 Auth 令牌并将其与每个 API 调用一起传递。
【讨论】: