【问题标题】:ASP.NET Core API: Authentication popup is not showing up in Swagger UIASP.NET Core API:身份验证弹出窗口未显示在 Swagger UI 中
【发布时间】:2021-06-27 06:47:34
【问题描述】:

我有一个带有 Swagger 的 ASP.NET Core Web API,使用 Swashbuckle 集成。我已经使用操作过滤器在 Swagger UI 上成功集成了授权,因为我不想为匿名 API 显示挂锁。

.OperationFilter<AuthorizeFilter>()

在过滤器中,我已经为 Swagger UI 注册了基本的身份验证安全要求。

我的问题是,即使在 Swagger UI 上的 API 中进行身份验证,我也不再看到单击挂锁图标时出现的漂亮的身份验证弹出窗口。

有人可以回答吗,为什么我现在看不到身份验证弹出窗口?

【问题讨论】:

    标签: asp.net-core swagger swashbuckle.aspnetcore


    【解决方案1】:

    假设您有一些受[Authorize] 属性保护的端点(也可以放在控制器上)。

    [Route("")]
    public class HelloController : ControllerBase
    {
        [Authorize]
        [HttpGet("secure")]
        public IActionResult GetSomethingPrivate()
        {
            return Ok("secret");
        }
    
        [HttpGet("public")]
        public IActionResult GetSomethingPublic()
        {
            return Ok("hey");
        }
    }
    

    您需要定义适合您需求的安全方案。 但不要全局要求,而是将其添加到操作过滤器中。这里我添加了一个简单的令牌认证:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "ApiPlayground", Version = "v1" });
            c.AddSecurityDefinition("token", new OpenApiSecurityScheme
            {
                Type = SecuritySchemeType.ApiKey,
                In = ParameterLocation.Header,
                Name = HeaderNames.Authorization,
                Scheme = "Bearer"
            });
            // dont add global security requirement
            // c.AddSecurityRequirement(/*...*/);
            c.OperationFilter<SecureEndpointAuthRequirementFilter>();
        });
    }
    

    这里是操作过滤器,它引用了我们刚刚创建的token auth 方案。它检查端点是否需要身份验证,然后添加要求。

    internal class SecureEndpointAuthRequirementFilter : IOperationFilter
    {
        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            if (!context.ApiDescription
                .ActionDescriptor
                .EndpointMetadata
                .OfType<AuthorizeAttribute>()
                .Any())
            {
                return;
            }
    
            operation.Security = new List<OpenApiSecurityRequirement>
            {
                new OpenApiSecurityRequirement
                {
                    [new OpenApiSecurityScheme
                    {
                        Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "token" }
                    }] = new List<string>()
                }
            };
        }
    }
    

    当您运行应用程序时,它会按照您的预期运行:

    身份验证弹出窗口也是如此:

    奖励:使用基本身份验证

    使用以下值定义新的安全方案:

    public void ConfigureServices(IServiceCollection services)
    {
        // ...
        services.AddSwaggerGen(c =>
        {
            // ...
            // basic auth scheme (username + password)
            c.AddSecurityDefinition("basic", new OpenApiSecurityScheme
            {
                Type = SecuritySchemeType.Http,
                Scheme = "basic"
            });
            // dont add global security requirement
            // c.AddSecurityRequirement(/*...*/);
            c.OperationFilter<SecureEndpointAuthRequirementFilter>();
        });
    }
    

    然后更新操作过滤器以引用basic auth scheme:

    internal class SecureEndpointAuthRequirementFilter : IOperationFilter
    {
        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            if (!context.ApiDescription
                .ActionDescriptor
                .EndpointMetadata
                .OfType<AuthorizeAttribute>()
                .Any())
            {
                return;
            }
    
            operation.Security = new List<OpenApiSecurityRequirement>
            {
                new OpenApiSecurityRequirement
                {
                    [new OpenApiSecurityScheme
                    {
                        Reference = new OpenApiReference
                        {
                            Type = ReferenceType.SecurityScheme, 
                            Id = "basic" // <-- changed "token" -> "basic"
                        }
                    }] = new List<string>()
                }
            };
        }
    }
    

    这是身份验证弹出窗口的外观:

    登录后,请求包含正确的Authorization 标头。

    【讨论】:

    • 感谢您的回答,无论如何我所做的完全一样,唯一的变化是我使用的是基本身份验证。试图找出我的代码中缺少什么。
    • @DarshaniJayasekara 我还在我的答案中添加了基本身份验证。查看更新
    • 谢谢,缺少的是安全定义。安全定义是给出弹出窗口的定义。没有它,一切正常,不显示弹出窗口。
    • Swagger 的文档是一个很棒的资源。 swagger.io/docs/specification/authentication。每当出现问题时,请查看文档以了解您的 OpenAPI 文档有何不同,并添加必要的配置。
    【解决方案2】:

    就我而言,我使用 JWT 令牌身份验证.NET Core API。我使用以下代码使用授权令牌配置招摇。此代码将添加全局安全要求。

    在启动类ConfigureServices方法中。

            //Swagger Configuration
    
            services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo
                {
                    Title = "API",
                    Version = "v2",
                    Description = "Your Api Description"
                });
                options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                {
                    Description = "JWT Authorization header using the Bearer scheme (Example: 'Bearer 12345abcdef')",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey,
                    Scheme = "Bearer"
                });
                options.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id = "Bearer"
                            }
                        },
                        Array.Empty<string>()
                    }
                });
            });
    

    配置方法

            app.UseSwagger();
    
            app.UseSwaggerUI(options =>
            {
                options.SwaggerEndpoint("/swagger/v1/swagger.json", "API");
            });
    

    API项目运行后右侧会出现Authorize按钮。单击授权按钮授权弹出窗口打开,然后在文本框中使用“Bearer token”传递令牌。

    授权对我来说很好。

    【讨论】:

    • 这将添加一个全局安全要求。不是 OP 要求的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-29
    • 2019-07-16
    • 2018-09-14
    • 1970-01-01
    • 2021-10-25
    • 2020-08-28
    • 2022-09-30
    相关资源
    最近更新 更多