Web Api 如何在 Swagger 中为所有 API 添加 Header 参数

Posted

技术标签:

【中文标题】Web Api 如何在 Swagger 中为所有 API 添加 Header 参数【英文标题】:Web Api How to add a Header parameter for all API in Swagger 【发布时间】:2017-05-20 11:22:51 【问题描述】:

我搜索了添加请求标头参数的可能方法,该参数将自动添加到我的web-api 中的每个方法中,但我找不到明确的方法。

在搜索时,我发现 OperationFilter() 方法必须对其进行处理。

【问题讨论】:

想知道这是否可以通过 Swagger UI 完成? Follow this link. I have given answer there and it is working 【参考方案1】:

是的,您可以通过从 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>();

重建并享受。

【讨论】:

@SoftwareEngineer 似乎问题出在试图从 IOperationFilter 继承的 `AddRequiredHeaderParameter` 类中,请确保您安装了 swagger 并将其引用到您的项目中。 @Saveen 我不确定我是否理解您的意思,但是此代码会将相同的参数添加到您拥有的所有 API 中。如果不取消您的函数参数,它只会将这个与与每个 API 函数关联的其他参数相加。 @RamyMohamed 我通过对上述代码稍作修改,找到了在特定操作方法中添加参数的解决方案。感谢您提供上面的参考代码。 @RamyMohamed 知道为什么我们要检查 operation.Parameters 是否为空吗? this变为null的用例是什么? 我试过这个。客户标头位于 httpContext.Request.Headers 结果集的结果视图下,但是当我执行 var key = httpContext.Request.Headers.Where(z => z.Key == "CUSTOMKEY").FirstOrDefault();我得到的关键是[null,null]。有什么想法吗?【参考方案2】:

您也可能有一个基本模型类并使用属性 [FromHeader] 来获取应在自定义标头中发送的属性。像这样的东西:

public class AuthenticatedRequest

    [FromHeader(Name = "User-Identity")]
    public string UserIdentity  get; set; 

至少它适用于 ASP.NET Core 2.1 和 Swashbuckle.AspNetCore 2.5.0。

【讨论】:

ASP.Net Core 3 和 Swashbuckle.AspNetCore 5.0.0-rc4 似乎不起作用。生成的文档将整个类作为请求主体。【参考方案3】:

添加自定义标题的另一种方法是将参数添加到控制器操作中。 以下示例将x-test 参数添加到 UI:

[HttpPost]
public IActionResult Test([FromHeader(Name="x-test")][Required] string requiredHeader)

    return Ok();

【讨论】:

请注意,[FromHeader] 属性仅适用于使用 ASP.Net Core 而非完整 .Net 的 WebAPI 实例。 我们在 WebAPI 2.0 非 .net 核心中是否有类似 FromHeader 的东西..?【参考方案4】:

用户“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>();

【讨论】:

谢谢它可以工作,但我必须在 5.0.0-rc2 中将参数设为可选(Required=false)) - 否则我无法尝试(看起来像是一个 swashbucjke 错误)。 @wille-esteche 我就是这样做的,但它不起作用。它曾经在旧版本上工作,就像在接受的答案中一样。当我要求为 true 时,UI 会因验证错误而失败,如果要求为 false,则永远不会发送授权标头。 回答***.com/questions/58179180/… 有效!但不要忘记在您的实际令牌前添加“Bearer” 只是补充一点,我的控制器操作正在使用 AuthorizeAttribute 并且上面的代码不起作用,因为 isAuthorized 总是错误的。我也为此添加了检查,它起作用了: var hasAuthorizeAttribute = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType().Any() || context.MethodInfo.GetCustomAttributes(true).OfType().Any(); Type = "String" 更改为"Type = "string" 让SwaggerUI 再次使用required = true 属性!【参考方案5】:

对于 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 中的标头实现添加任何标头。

【讨论】:

【参考方案6】:

我已经稍微改进了尊敬的 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)
                    
            );
        
    

    

【讨论】:

这个答案很适合我。我已经为控制器方法完成了一些自定义属性,这些属性将读取额外的请求参数,并且通过这种方法我可以在 swagger 中记录那些“隐藏”参数。我的想法是实现一个接口,其中包含获取标题名称、描述、isrequired 和 defaultvalue 的方法。【参考方案7】:

如果在 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.csConfiguration.EnableSwagger 中提供此类的参考:

c.OperationFilter<AddHeaderParameters>();

重要需要注意的是,标头名称应该与您为 API 创建的实际标头匹配。

【讨论】:

【参考方案8】:

在我的情况下(.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 --&gt; ConfigureServices --&gt; AddSwaggerGen 添加

c.OperationFilter<AddRequiredHeaderParameter>();

【讨论】:

谢谢,它对我有用。我使用.NET 5【参考方案9】:

这适用于 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

【讨论】:

【参考方案10】:

不确定 .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
            );
        
    

【讨论】:

【参考方案11】:

另一个定制的实现:

Web API (.Net 5) Swashbuckle.AspNetCore.Swagger (6.2.3) Swashbuckle.AspNetCore.SwaggerGen (6.2.3) Swashbuckle.AspNetCore.SwaggerUI (6.2.3)

按照此线程的一些答案确实让我获得了授权的必填字段。但是我遇到了不同的问题。我需要修复以下问题:

在需要身份验证的 API 操作旁边显示锁定标志。对于匿名操作,没有必要设置Authorization 字段。 对于每个 API 端点,我都不想输入授权密钥。如果我们要一次测试几个 API,这将成为一项多余的工作。所以我需要一个点来放置 Auth 密钥并从 Swagger UI 执行 API。 Swagger UI 将在需要时处理 Auth 部分。 我不想在可能需要编辑许多操作的控制器操作中添加自定义过滤器或代码。 最后但并非最不重要的一点是,我遇到了一个问题,我确实在 Swagger UI 上获得了所需的 Authorization 字段,但没有在请求标头中与其他 API 字段一起回发。

为了克服上述问题,我做了以下工作:

创建IOperationFilter 类型过滤器以指示哪些 API 端点需要身份验证,哪些是匿名类型 Swagger UI 上的一个按钮,用于弹出一个输入我的身份验证令牌的窗口,该令牌将自动与来自 Swagger UI 的 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 调用一起传递。

【讨论】:

以上是关于Web Api 如何在 Swagger 中为所有 API 添加 Header 参数的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Nx monorepo 中为 NestJS 和 Angular 之间共享的 API 接口启用 Swagger?

如何在 OpenAPI (Swagger) 中为相同的 HTTP 状态代码定义不同的响应?

如何在 Gradle 中为 OpenAPI 3.0 使用 Swagger Codegen?

使用 Header 的 Web Api 版本控制,我们如何使用 Net Framework MVC Api 在 Swagger UI 上使用它

Web Api 2.0中使用Swagger生成Api文档的2个小Tips

.Net Core Web API Swagger 没有找到该网址的网页:http://localhost/swagger