【问题标题】:Swagger UI: pass custom Authorization headerSwagger UI:传递自定义授权标头
【发布时间】:2016-08-11 21:10:33
【问题描述】:

我在 ASP.NET Web API 上使用 Swashbuckle 和 Swagger。我正在尝试找到一种通过 Swagger UI 传递包含 Bearer 令牌的授权标头的方法。我一直在四处寻找,但所有答案似乎都指向this 链接。

但是,这假定标题的内容是预先知道的。我真的需要一种方法来更改 Swagger UI 中的标题(就在点击“试试看!”按钮之前),因为 Bearer 令牌每小时都会过期。类似于 Postman 允许您添加标题的方式。

这似乎是一个简单得可笑的问题,但答案是什么?

【问题讨论】:

    标签: asp.net-web-api swagger swagger-ui swashbuckle


    【解决方案1】:

    我们在项目中遇到了同样的问题。我还想将标头参数添加到 Swagger UI 网站。我们就是这样做的:

    1.定义一个 OperationFilter 类 每次构建 Swagger 时,都会在每个 API 操作上执行 OperationFilter。根据您的代码,将根据您的过滤器检查操作。在这个例子中,我们让每个操作都需要 header 参数,但在具有 AllowAnonymous 属性的操作上使其可选。

        public class AddAuthorizationHeader : IOperationFilter
        {
            /// <summary>
            /// Adds an authorization header to the given operation in Swagger.
            /// </summary>
            /// <param name="operation">The Swashbuckle operation.</param>
            /// <param name="schemaRegistry">The Swashbuckle schema registry.</param>
            /// <param name="apiDescription">The Swashbuckle api description.</param>
            public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
            {
                if (operation == null) return;
    
                if (operation.parameters == null)
                {
                    operation.parameters = new List<Parameter>();
                }
    
                var parameter = new Parameter
                {
                    description = "The authorization token",
                    @in = "header",
                    name = "Authorization",
                    required = true,
                    type = "string"
                };
    
                if (apiDescription.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any())
                {
                    parameter.required = false;
                }
    
                operation.parameters.Add(parameter);
            }
        }
    

    2。告诉 Swagger 使用这个 OperationFilter 在SwaggerConfig中,只需添加操作过滤器应该使用如下:

        c.OperationFilter<AddAuthorizationHeader>();
    

    希望对你有所帮助!

    【讨论】:

    • 貌似最新版的Swashbuckle改了Operation类去掉了参数过滤类?有什么想法吗?
    • 如果我创建该过滤器,我的所有操作都需要它吗?如何排除不需要的控制器操作?
    • @D.B 使用 [AllowAnonymous] 为您不希望应用身份验证的操作装饰控制器操作后,更新“AddAuthorizationHeader”以仅在不添加 [AllowAnonymous] 的位置添加参数。伪:如果 !apiDescription.ActionDescriptor.GetCustomAttributes().Any()) 那么 operation.parameters.Add(parameter);
    【解决方案2】:

    创建一个实现IOperationFilter的新操作过滤器。

    public class AuthorizationHeaderOperationFilter : IOperationFilter
    {
        /// <summary>
        /// Adds an authorization header to the given operation in Swagger.
        /// </summary>
        /// <param name="operation">The Swashbuckle operation.</param>
        /// <param name="context">The Swashbuckle operation filter context.</param>
        public void Apply(Operation operation, OperationFilterContext context)
        {
            if (operation.Parameters == null)
            {
                operation.Parameters = new List<IParameter>();
            }
    
            var authorizeAttributes = context.ApiDescription
                .ControllerAttributes()
                .Union(context.ApiDescription.ActionAttributes())
                .OfType<AuthorizeAttribute>();
            var allowAnonymousAttributes = context.ApiDescription.ActionAttributes().OfType<AllowAnonymousAttribute>();
    
            if (!authorizeAttributes.Any() && !allowAnonymousAttributes.Any())
            {
                return;
            }
    
            var parameter = new NonBodyParameter
            {
                Name = "Authorization",
                In = "header",
                Description = "The bearer token",
                Required = true,
                Type = "string"
            };
    
            operation.Parameters.Add(parameter);
        }
    }
    

    在您的 Startup.cs 文件中配置服务。

            services.ConfigureSwaggerGen(options =>
            {
                options.OperationFilter<AuthorizationHeaderOperationFilter>();
            });
    

    【讨论】:

    • 这是使其与 .NET Core 2.x 和 Swashbuckle 4.x 一起使用的方法。 +1 为 NonBodyParameter 出现在 StackOverflow 上关于此主题的其他示例中都没有出现!
    • 请注意,对于 Swashbuckle 5,您不再为此使用 IOperationFilter,现在使用 AddSecurityDefinition 对其进行配置。
    • 如果需要其他非身份验证标头参数 Swashbuckle 5 ,像上面的示例方法中的 NonBodyParameter 是否仍然有用?
    • 是的,我想这会很有用。
    【解决方案3】:

    根据您收集Authorization 标头的方式以及您是否希望代码处理所有内容,或者您​​是否希望用户能够输入他们想要的任何Authorization 标头,您可以采用不同的方式进行操作。

    当我第一次尝试这个时,我能够在每个端点的参数字段区域中显示 Authorization 标头文本,用户可以在其中键入 Authorization 标头,但这不是我想要的。

    在我的情况下,我必须使用用户的 cookie 向 /token 端点发送请求,以获得有效的 Authorization 令牌。所以我做了很多事情来实现这一点。

    首先在SwaggerConfig.cs 中,我取消了c.BasicAuth() 的注释以将基本身份验证方案添加到API 架构中,并且我还注入了一个自定义index.html 页面,在该页面中我插入了一个AJAX 请求以获取Authorization 令牌,使用用户的 cookie(index.html 代码如下所示):

    public static void Register() {
    
        System.Reflection.Assembly thisAssembly = typeof(SwaggerConfig).Assembly;
    
        System.Web.Http.GlobalConfiguration.Configuration
                    .EnableSwagger(c => {
                        ...
    
                        c.BasicAuth("basic").Description("Bearer Token Authentication");
    
                        ...
                    })
                    .EnableSwaggerUi(c => {
                        ...
    
                        c.CustomAsset("index", thisAssembly, "YourNamespace.index.html");
    
                        ...
                    });
    }
    

    然后前往here 下载swashbuckle index.html,我们将自定义它以插入Authorization 标头。

    下面我简单地使用有效的 cookie 对我的 /token 端点进行 AJAX 调用,获取 Authorization 令牌,并将其提供给 swagger 以与 window.swaggerUi.api.clientAuthorizations.add() 一起使用:

    ...
    
    function log() {
      if ('console' in window) {
        console.log.apply(console, arguments);
      }
    }
    
    $.ajax({
        url: url + 'token'
      , type: 'POST'
      , data: { 'grant_type': 'CustomCookie' }
      , contentType: 'application/x-www-form-urlencoded'
      , async: true
      , timeout: 60000
      , cache: false
      , success: function(response) {
            console.log('Token: ' + response['token_type'] + ' ' + response['access_token']);
            window.swaggerUi.api.clientAuthorizations.add("key", new SwaggerClient.ApiKeyAuthorization("Authorization", response['token_type'] + ' ' + response['access_token'], "header"));
        }
      , error: function(request, status, error) {
            console.log('Status: ' + status + '. Error: ' + error + '.');
        }
    });
    

    我从 AJAX 调用中删除了一些内容以使其更简单,显然您的实现可能会有所不同,具体取决于您收集Authorization 令牌和内容的方式,但这给了您一个想法。如果您有任何具体问题或疑问,请告诉我。

    *编辑:没有注意到您实际上确实希望用户输入他们的Authorization 标头。在这种情况下,这很容易。我使用了this 帖子。只需创建以下类来完成这项工作:

    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 = "Foo-Header",
                @in = "header",
                type = "string",
                required = true
            });
        }
    }
    

    然后像这样将课程添加到我的SwaggerConfig

    ...
    c.OperationFilter<AddRequiredHeaderParameter>();
    ...
    

    【讨论】:

    • 感谢您的回答。我对你提到的第一件事很感兴趣;即“当我第一次尝试这个时,我能够在每个端点的参数字段区域中显示授权标头文本,用户可以在其中输入授权标头”。你是怎么做的?正如问题中提到的,我希望用户键入授权标头,我不希望自动填写授权标头。
    • @fikkatra 抱歉,不知道我是怎么错过的。见编辑。
    【解决方案4】:

    在 Swashbuckle 5 中,这是在 Startup.cs 中使用以下文件完成的。

    // Register the Swagger generator, defining one or more Swagger documents
    services.AddSwaggerGen(c =>
    {
        c.AddSecurityDefinition("bearerAuth", new OpenApiSecurityScheme
        {
            Type = SecuritySchemeType.Http,
            Scheme = "bearer",
            BearerFormat = "JWT",
            Description = "JWT Authorization header using the Bearer scheme."
        });
        c.AddSecurityRequirement(new OpenApiSecurityRequirement
        {
            {
                new OpenApiSecurityScheme
                {
                    Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "bearerAuth" }
                },
                new string[] {}
            }
        });
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-23
      • 2020-05-10
      • 2011-12-09
      • 2015-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多