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

Web Api How to add a Header parameter for all API in Swagger

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

在搜索时我发现方法 OperationFilter() 必须对此做些什么。

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

重建,尽情享受。

您也可能有一个基本模型 class 并使用属性 [FromHeader] 作为应该在自定义 headers 中发送的属性。是这样的:

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

至少它在 ASP.NET Core 2.1 和 Swashbuckle.AspNetCore 2.5.0 上工作正常。

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

[HttpPost]
public IActionResult Test([FromHeader(Name="x-test")][Required] string requiredHeader)
{
    return Ok();
}

用户“GT”写的是正确的,但它不适用于 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>();

对于 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 中为 header 实施添加任何 header。

我对恭敬的 Wille Esteche 的回答做了一些改进。 如果您不想将 headers 应用于所有方法,而只想应用于您选择的控制器方法,则可以使用属性。

    [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)
    { .....
    

属性class:

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,并且需要添加 headers 以从 swagger UI.

获取输入

创建一个 class 继承自 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"
        });    
    }
}

Configuration.EnableSwagger 中的 SwaggerConfig.cs 中引用此 class 为:

c.OperationFilter<AddHeaderParameters>();

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

在我的例子中 (.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

不确定 2021 年 9 月发布的 .net 5.0 是否回答了这个问题,但我采纳了 Rami 的回答并将其改编为以下内容:

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
            });
        }
    }
}

另一个自定义实现:

  • 网络 API (.Net 5)
  • Swashbuckle.AspNetCore.Swagger (6.2.3)
  • Swashbuckle.AspNetCore.Swagger一代 (6.2.3)
  • Swashbuckle.AspNetCore.SwaggerUI (6.2.3)

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

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

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

  • 创建一个 IOperationFilter 类型过滤器以指示哪些 API 端点需要身份验证,哪些是匿名类型
  • Swagger 上的一个按钮 UI 用于弹出窗口以输入我的 Auth 令牌,该令牌将自动与来自 Swagger 的 API 调用一起使用 UI

代码如下:

#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 token 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 描述符页面的顶部为您提供一个授权按钮。单击该按钮将出现一个弹出窗口 window,您可以在其中输入 Auth 令牌并在每次 API 调用时将其传递。