ASP.NET Core 同时支持多种认证方式 | Swagger 支持

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ASP.NET Core 同时支持多种认证方式 | Swagger 支持相关的知识,希望对你有一定的参考价值。

前言

上次,我们实现了《ASP.NET Core 同时支持多种认证方式》:

services.AddAuthentication()
    .AddDemoAuthentication(options =>  )
    .AddJwtBearer(options =>
    
        ...
    );

我们还希望为 Swagger 也添加多种认证支持。

原来为支持 JWT 认证,Swagger 相关配置代码是这样的:

services.AddSwaggerGen(c =>

    c.SwaggerDoc("v1", new OpenApiInfo  Title = "WebApplication9", Version = "v1" );

    c.AddSecurityDefinition("bearerAuth", new OpenApiSecurityScheme()
    
        Type = SecuritySchemeType.Http,
        Scheme = "bearer",
    );
    c.AddSecurityRequirement(new OpenApiSecurityRequirement 
    
        new OpenApiSecurityScheme
        
        Reference = new OpenApiReference
        
            Type = ReferenceType.SecurityScheme,
            Id = "bearerAuth"
        
        ,
        new string[]  
    
    );

依葫芦画瓢,添加如下代码:

c.AddSecurityDefinition("demoAuth", new OpenApiSecurityScheme()

    
    Type = SecuritySchemeType.ApiKey,
    In = ParameterLocation.Query,
    Name = "_key",
    Scheme = "demo",
);
c.AddSecurityRequirement(new OpenApiSecurityRequirement 

    new OpenApiSecurityScheme
    
    Reference = new OpenApiReference
    
        Type = ReferenceType.SecurityScheme,
        Id = "demoAuth"
    
    ,
    new string[]  

);

Swagger 可以正常显示 Authorize 页面:

但是,发现一个问题, 每次请求都会发送所有的认证信息,即使我们的方法只需要其中的一种:

解决思路

这是因为,我们使用了AddSecurityRequirement增加了全局的安全要求。

应该根据方法上设置的AuthenticationSchemes添加对应的安全要求。

针对这一需求,可以使用 IOperationFilter 接口实现操作筛选器。检索 ApiDescription 以获取相关信息,例如方法级别的AuthorizeAttribute

实现

首先,创建SecuritySchemeOperationFilter继承自IOperationFilter,实现 Apply 方法:

internal class SecuritySchemeOperationFilter : IOperationFilter

    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    
        if (context != null && operation != null)
        
            var authenticationSchemes = context.MethodInfo
                    .GetCustomAttributes(true)
                    .OfType<AuthorizeAttribute>()
                    .SelectMany(attr => attr.AuthenticationSchemes.Split(','))
                    .Distinct();

            string id = "";

            if (authenticationSchemes.Contains("Bearer"))
            
                id = "bearerAuth";
            
            else if (authenticationSchemes.Contains("Demo"))
            
                id = "demoAuth";
            

            operation.Security = new List<OpenApiSecurityRequirement>
            
                new OpenApiSecurityRequirement 
                
                    new OpenApiSecurityScheme
                    
                    Reference = new OpenApiReference
                    
                        Type = ReferenceType.SecurityScheme,
                        Id = id
                    
                    ,
                    new string[]  
                
            
            ;
        
    

在上面的代码中,我们检查 API 上指定的授权过滤器,并在授权过滤器的基础上添加了适当的安全要求。

另外,修改一下 Swagger 注册代码:

services.AddSwaggerGen(c =>

    c.SwaggerDoc(...);

    c.AddSecurityDefinition("bearerAuth", ...);
    c.AddSecurityDefinition("demoAuth", ...);
    
    c.OperationFilter<SecuritySchemeOperationFilter>();
);

现在可以看到,对于OnlyForBearer API,只发送Bearer授权头,而不再发送Query查询字符串:

结论

今天,我们通过 IOperationFilter 实现了 Swagger 同时支持多种认证方式。

添加微信号【MyIO666】,邀你加入技术交流群

以上是关于ASP.NET Core 同时支持多种认证方式 | Swagger 支持的主要内容,如果未能解决你的问题,请参考以下文章

无私分享:ASP.NET CORE 项目实战(第十二章)添加对SqlServerMySqlOracle的支持

ASP.NET Core 实现基于 ApiKey 的认证

[Asp.Net Core]Filter的多种注册

ASP.NET Core框架探索之Authentication

《ASP.NET Core 6框架揭秘》实例演示[24]:中间件的多种定义方式

ASP.NET Core认证授权方案