【问题标题】:How to send custom headers with requests in Swagger UI?如何在 Swagger UI 中发送带有请求的自定义标头?
【发布时间】:2017-05-02 00:39:04
【问题描述】:

我在 API 中有一些端点 - /user/login/products

在 Swagger UI 中,我将 emailpassword 发布到 /user/login,作为回复,我收到了 token 字符串。

然后,我可以从响应中复制令牌,并希望将其用作Authorization 标头值,用于对所有网址(如果存在)的请求,并以/products 为例。

我应该在 Swagger UI 页面的某处手动创建文本输入,然后将令牌放在那里并以某种方式注入请求,还是有工具可以更好地管理它?

【问题讨论】:

    标签: api authorization swagger swagger-ui


    【解决方案1】:

    在 ASP.NET Web API 中,在 Swagger UI 上传入标头的最简单方法是在 IOperationFilter 接口上实现 Apply(...) 方法。

    将此添加到您的项目中:

    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&lt;T&gt;()从上面注册过滤器:

    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 方法禁用它?例如,用户登录不需要将该标头作为返回身份验证令牌传递。这将“MyHeaderField”添加到所有 API 方法 Swagger 文档中。
    • @NeilHodges 你明白了吗。我什至在寻找它。
    • @gee'K'iran 您可以通过检查 operation 和 apiDescription 参数并选择是否添加标头来选择性地应用该功能。
    • 感谢您不包括命名空间。
    • 我试过这个。客户标头位于 httpContext.Request.Headers 结果集的结果视图下,但是当我执行 var key = httpContext.Request.Headers.Where(z => z.Key == "CUSTOMKEY").FirstOrDefault();我得到的关键是[null,null]。有什么想法吗?
    【解决方案2】:

    你可以在你的请求中添加一个 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 对象定义了安全方案。

    security 对象(在 Swagger–OpenAPI 中称为“安全要求”)将安全方案应用于给定上下文。在我们的例子中,我们通过将安全要求声明为顶层来将其应用于整个 API。我们可以选择在单个路径项和/或方法中覆盖它。

    这将是指定安全方案的首选方式;它替换了第一个示例中的 header 参数。不幸的是,至少在我目前的测试中,Swagger-UI 没有提供文本框来控制这个参数。

    【讨论】:

    • 我在 python 模块中定义参数,该模块使用模型定义端点,然后我使用 RequestParse 在 swagger 文档中添加输入字段。该文本文件如何以及在何处添加 `-name: auth` ?
    • @Ted,我们没有办法在 openapi2.0 中提供自定义的 json(object) 类型信息吗? this attempt fails to compile
    【解决方案3】:

    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"
    

    【讨论】:

    • 是哪个swagger版本?在 swagger 2.4.0 中找不到授权按钮。
    【解决方案4】:

    还可以将属性 [FromHeader] 用于应在自定义标头中发送的 Web 方法参数(或模型类中的属性)。像这样的:

    [HttpGet]
    public ActionResult Products([FromHeader(Name = "User-Identity")] string userIdentity)
    

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

    【讨论】:

    • 这只适用于 MVC 而不是 Web Api 解决方案(至少我是这么认为的,因为它在我的 Web Api 解决方案上失败了)
    • @bleh10 任何详细信息为什么它对您的解决方案失败?对于我的 Web API 项目,它工作得很好。
    • 不知道为什么,它迫使我添加mvc库,当我做VS时感到困惑,明天我会重新检查,因为我今天不上班,并会添加我遇到的错误!跨度>
    • 我已经更正了,我只是再次尝试它并且它有效,唯一的问题是现在我必须添加“System.Web.Http”。在 HttpGET 和 route 和 FromBody 之前,这有点烦人,但迄今为止最好的解决方案!编辑:一个更好的解决方案(不知道为什么我以前没有想到它)所以我不重新编辑我所有的控制器是添加 Microsoft.AspNetCore.Mvc。在 FromHeader 之前,现在一切正常!
    • 关于添加“System.Web.Http”。在 HttpGET 和 route 和 FromBody 之前 - 您可以对该命名空间使用“using”指令来避免这种重复的代码。因此,只需在定义控制器的文件开头添加using System.Web.Http;
    【解决方案5】:

    这是 ASP.NET Core Web Api/Swashbuckle 组合的一个更简单的答案,它不需要您注册任何自定义过滤器。第三次是你知道的魅力:)。

    将以下代码添加到您的 Swagger 配置将导致出现“授权”按钮,允许您输入要为所有请求发送的不记名令牌。询问时不要忘记将此令牌输入为Bearer &lt;your token here&gt;

    请注意,下面的代码将为任何和所有请求和操作发送令牌,这可能是也可能不是您想要的。

    
        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

    【讨论】:

      【解决方案6】:

      我最终来到这里是因为我试图根据我添加到我的 API 方法中的 [Authentication] 属性有条件地在 Swagger UI 中添加标题参数。根据@Corcus 在评论中列出的提示,我能够得出我的解决方案,并希望它能对其他人有所帮助。

      使用反射,它检查嵌套在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
                  });
              }
          }
      
      
      }
      

      【讨论】:

      • 对于那些正在尝试使用 API Key .Net core 2.1 c.AddSecurityRequirement(new Dictionary&lt;string, IEnumerable&lt;string&gt;&gt; { { "ApiKeyAuth", new string[0] } }); *.com/questions/49908577/…
      【解决方案7】:

      对于那些使用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 将包含一个 授权 按钮。

      【讨论】:

        【解决方案8】:

        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
        

        【讨论】:

          【解决方案9】:

          更新 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 生成了不正确的定义并错过了包含 Authorizeation 标头。所以请仔细检查您使用的 OpenAPI 版本。

          【讨论】:

            【解决方案10】:

            免责声明:此解决方案使用 Header。

            如果有人正在寻找一种懒惰的方式(也在 WebApi 中),我建议:

            public YourResult Authorize([FromBody]BasicAuthCredentials credentials)

            你不是从标题中得到的,但至少你有一个简单的选择。 您始终可以检查对象是否为空并回退到标头机制。

            【讨论】:

              最近更新 更多