在 Swashbuckle 中启用不记名令牌(Swagger 文档)

Enable bearer token in Swashbuckle (Swagger document)

我创建了一个 asp.net webapi 应用程序,它使用 个人帐户安全性 ,以便默认启用不记名令牌。它工作正常,因此我可以毫无问题地在 Postman 中测试它们。

当我尝试集成 Swashbuckle 的 Swagger UI 时,问题来了。我通过以下方式安装了 Swashbuckle:

Install-Package Swashbuckle

然后改变SwaggerConfig.cs:

GlobalConfiguration.Configuration
    .EnableSwagger(c =>
    {
        c.ApiKey("Token")
            .Description("Filling bearer token here")
            .Name("Authorization")
            .In("header");
    }
    .EnableSwaggerUi(c =>
    {
        c.EnableApiKeySupport("Authorization", "header");
    };

启动我的应用程序并填写 Bearer 令牌:

但是当我运行需要授权的api请求时,它不起作用。这是屏幕截图:

不记名令牌已添加到 header 中的 Authorization。但是我还是报401错误。我想知道是不是因为token被编码了(SPACE被%20代替了)?任何的想法?谢谢

顺便说一句,我想知道如何在我的 Swagger 文档中添加 /token,以便我可以在 Swagger UI 中获取令牌。

更新

下面详述的问题现已在 Swashbuckle v5.5.0 中得到解决。

问题

只是 运行 进入完全相同的问题。我认为根本原因是 Swashbuckle's source code:

中的这一行
var key = encodeURIComponent($('#input_apiKey')[0].value);

这是 HTML 输入字段的值通过 URL 编码将 space 变成 %20 的地方。我打算在 Swashbuckle repo on GitHub.

中打开一个问题

解决方法

在该问题得到解决之前,这里有一个解决方法,它基于使用注入到 Swagger UI:

中的 Javascript 文件替换上述行
  1. 在安装了 Swashbuckle 的项目中,创建一个新文件夹并将其命名为 "Swagger".

  2. 在新文件夹中创建一个名为 "SwaggerUiCustomization.js" 的新 Javascript 文件并将此脚本放入其中:

    (function () {
        function addApiKeyAuthorization() {
            var key = $('#input_apiKey')[0].value;
            if (key && key.trim() != "") {
                var apiKeyAuth = new SwaggerClient.ApiKeyAuthorization(swashbuckleConfig.apiKeyName, key, swashbuckleConfig.apiKeyIn);
                window.swaggerUi.api.clientAuthorizations.add("api_key", apiKeyAuth);
                log("added key " + key);
            }
        }
        $('#input_apiKey').change(addApiKeyAuthorization);
    })();
    
  3. 在解决方案资源管理器中,选择文件并按 Alt+Enter 键编辑其属性。在 Properties window 中,将文件的 Build Action 更改为 Embedded Resource

  4. 在您的 SwaggerConfig.cs 文件中的 EnableSwaggerUi() 代码块内添加以下行: c.InjectJavaScript(thisAssembly, "<Project_Default_Namespace>.Swagger.SwaggerUiCustomization.js");
    当然,请务必将 <Project_Default_Namespace> 替换为您项目的默认名称 space。

  5. 运行 您的项目并在文本框中输入 "Bearer "。当您调用控制器操作时,您应该在服务器端获得完全相同的值 - 使用白色 space 而不是 %20%

注意:此示例使用 Json Web 令牌。

可以设置您的代码,因此授权字符串中不需要 "Bearer"。

WebApi 项目中用于检索令牌的代码(参见下面代码段中的 token = ...):

private static bool TryRetrieveToken(HttpRequestMessage request, out string token)
    {
        token = null;
        IEnumerable<string> authzHeaders;
        if (!request.Headers.TryGetValues("Authorization", out authzHeaders) || authzHeaders.Count() > 1)
        {
            return false;
        }
        var bearerToken = authzHeaders.ElementAt(0);
        token = bearerToken.StartsWith("Bearer ") ? bearerToken.Substring(7) : bearerToken;
        return true;
    }

Swagger ApiKey:

c.ApiKey("Authorization")
                        .Description("Filling bearer token here")
                        .Name("Bearer")
                        .In("header");

Swagger 启用 ApiKey 支持:

c.EnableApiKeySupport("Authorization", "header");

将令牌粘贴到 Swagger 中的 Api_Key 表单元素中 UI:

它在 Swagger 中的请求 header 中的样子:

在 asp.net 框架 Web API 中,我能够在 UI 上添加 Bearer 令牌并通过两种不同的方式使其正常工作。

方式一:

添加操作过滤器。创建以下 class :

public class AuthorizationHeaderParameterOperationFilter : 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 = "Authorization",
            @in = "header",
            description = "access token",
            required = false,
            type = "string",
            @default = "Bearer "
        });
    }
}

现在在 SwaggerConfig.cs 添加以下内容:

GlobalConfiguration.Configuration
            .EnableSwagger(c =>
                {
                     // other settings

                     c.OperationFilter<AuthorizationHeaderParameterOperationFilter>();
             })
            .EnableSwaggerUi(c =>
                {
                    // UI configurations
            });

方式二:

我们也可以使用DocumentFilter来迭代所有操作并添加header,在下面的操作中我们跳过实际获取用户名和密码并第一次提供令牌的操作:

public class SwaggerPathDescriptionFilter : IDocumentFilter
{
    private string tokenUrlRoute = "Auth";
    // the above is the action which returns token against valid credentials
    private Dictionary<HeaderType, Parameter> headerDictionary;
    private enum HeaderType { TokenAuth };

    public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
    {
        CreateHeadersDict();

        var allOtherPaths = swaggerDoc.paths.Where(entry => !entry.Key.Contains(tokenUrlRoute)) //get the other paths which expose API resources and require token auth
            .Select(entry => entry.Value)
            .ToList();

        foreach (var path in allOtherPaths)
        {
            AddHeadersToPath(path, HeaderType.TokenAuth);
        }
    }

    /// <summary>
    /// Adds the desired header descriptions to the path's parameter list
    /// </summary>
    private void AddHeadersToPath(PathItem path, params HeaderType[] headerTypes)
    {
        if (path.parameters != null)
        {
            path.parameters.Clear();
        }
        else
        {
            path.parameters = new List<Parameter>();
        }

        foreach (var type in headerTypes)
        {
            path.parameters.Add(headerDictionary[type]);
        }

    }

    /// <summary>
    /// Creates a dictionary containin all header descriptions
    /// </summary>
    private void CreateHeadersDict()
    {
        headerDictionary = new Dictionary<HeaderType, Parameter>();


        headerDictionary.Add(HeaderType.TokenAuth, new Parameter() //token auth header
        {
            name = "Authorization",
            @in = "header",
            type = "string",
            description = "Token Auth.",
            required = true,
            @default = "Bearer "
        });
    }
}

然后我们需要在 SwaggerConfig.cs 中注册它:

GlobalConfiguration.Configuration
            .EnableSwagger(c =>
                {
                     // other settings

                     c.DocumentFilter<SwaggerPathDescriptionFilter>();
             })
            .EnableSwaggerUi(c =>
                {
                    // UI configurations
            });

现在我们将在 swagger UI 中看到 header 的令牌输入,例如:

OpenAPI 3更新,Swashbuckle.AspNetCore(6.7.1)全文地址:https://codeburst.io/api-security-in-swagger-f2afff82fb8e 为swagger添加JWT Bearer授权的代码。在 ConfigureServices 方法的 Startup.cs 中添加:

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[] { }}
    });
}