为了账号安全,请及时绑定邮箱和手机立即绑定

ASP Net Core 2.2 仅向需要授权的方法添加储物柜图标

ASP Net Core 2.2 仅向需要授权的方法添加储物柜图标

C#
慕森卡 2023-08-13 15:36:25
我目前拥有什么?我已经在我的 Web API 项目中实现了 swagger。我正在使用 JWT 授权,并[Authorize]在需要它的方法上使用属性。所以我想要一种简单的方法来发送需要授权的请求。在我的ConfigureServices课堂上,我添加了以下逻辑。services.AddSwaggerGen(c =>{    // Other swagger options    c.AddSecurityDefinition("Bearer", new ApiKeyScheme    {        In = "header",        Description = "Please enter into field the word 'Bearer' following by space and your JWT token",        Name = "Authorization",        Type = "apiKey"    });    c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>    {        { "Bearer", Enumerable.Empty<string>() },    });    // Other swagger options});其作用如下:它在 swagger 中添加了一个新按钮 - 授权。问题是,它还在每个方法旁边添加了一个“打开”储物柜图标。尽管如此,其中一些需要授权。当我使用授权按钮成功授权时(它基本上为每个请求添加了标头授权),我在所有请求上收到一个“关闭”的储物柜。 我知道这可能是所需的功能,表明将通过请求发送授权令牌。我想要一种方法来显示哪些方法需要授权,哪些不需要。我想要什么?例如,匿名方法的“开放”储物柜和具有[Authorize]属性的方法的“关闭”储物柜。它可能是一个附加图标,位于该图标旁边或用于修改该图标的行为,没问题。我怎样才能实现这个目标?可能的解决方案?我相信一个可能的解决方案是创建一个操作过滤器并遍历所有方法并将“某些内容”仅附加到那些具有[Authorize]属性的方法。这是最好的解决方案吗?如果是这样,你会如何实施?
查看完整描述

3 回答

?
沧海一幻觉

TA贡献1824条经验 获得超5个赞

因为距离我问这个问题已经过去一个多月了。我是这样做的。


我从 中删除了以下代码Startup.cs:


c.AddSecurityDefinition("Bearer", new ApiKeyScheme

{

    In = "header",

    Description = "Please enter into field the word 'Bearer' following by space and your JWT token",

    Name = "Authorization",

    Type = "apiKey"

});

c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>

{

    { "Bearer", Enumerable.Empty<string>() },

});

我添加了以下一项:


c.OperationFilter<AddAuthHeaderOperationFilter>();

当然还有AddAuthHeaderOperationFilter.cs:


    public class AddAuthHeaderOperationFilter : IOperationFilter

    {

        private readonly IHttpContextAccessor httpContextAccessor;


        public AddAuthHeaderOperationFilter(IHttpContextAccessor httpContextAccessor)

        {

            this.httpContextAccessor = httpContextAccessor;

        }


        public void Apply(Operation operation, OperationFilterContext context)

        {

            var filterDescriptor = context.ApiDescription.ActionDescriptor.FilterDescriptors;

            var isAuthorized = filterDescriptor.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);

            var allowAnonymous = filterDescriptor.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter);


            if (isAuthorized && !allowAnonymous)

            {

                if (operation.Parameters == null)

                    operation.Parameters = new List<IParameter>();


                operation.Parameters.Add(new NonBodyParameter

                {

                    Name = "Authorization",

                    In = "header",

                    Description = "JWT access token",

                    Required = true,

                    Type = "string",

                    //Default = $"Bearer {token}"

                });


                operation.Responses.Add("401", new Response { Description = "Unauthorized" });

                operation.Responses.Add("403", new Response { Description = "Forbidden" });


                operation.Security = new List<IDictionary<string, IEnumerable<string>>>();


                //Add JWT bearer type

                operation.Security.Add(new Dictionary<string, IEnumerable<string>>

                {

                    { "Bearer", new string[] { } }

                });

            }

        }

    }

很快,这个OperationFilter类只将储物柜图标添加到需要授权的方法中。不过储物柜总是打开的。所以这不是完美的解决方案,但目前还可以。


它看起来是这样的:

https://img1.sycdn.imooc.com//64d8886d0001f39906530147.jpg

查看完整回答
反对 回复 2023-08-13
?
慕码人2483693

TA贡献1860条经验 获得超9个赞

更改为以下内容(进行了一些额外的样式编辑):


public class AddAuthHeaderOperationFilter : IOperationFilter

{

    private readonly IHttpContextAccessor httpContextAccessor;


    public AddAuthHeaderOperationFilter(IHttpContextAccessor httpContextAccessor)

    {

        this.httpContextAccessor = httpContextAccessor;

    }


    public void Apply(Operation operation, OperationFilterContext context)

    {

        var filterDescriptor = context.ApiDescription.ActionDescriptor.FilterDescriptors;

        var isAuthorized = filterDescriptor.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);

        var allowAnonymous = filterDescriptor.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter);


        if (isAuthorized && !allowAnonymous)

        {

            if (operation.Parameters == null)

                operation.Parameters = new List<IParameter>();


            operation.Parameters.Add(new NonBodyParameter

            {

                Name = "Authorization",

                In = "header",

                Description = "JWT access token",

                Required = true,

                Type = "string"

            });


            operation.Responses.Add("401", new Response { Description = "Unauthorized" });

            operation.Responses.Add("403", new Response { Description = "Forbidden" });


            operation.Security = new List<IDictionary<string, IEnumerable<string>>>();


            //Add JWT bearer type

            operation.Security.Add(new Dictionary<string, IEnumerable<string>>

            {

                { "Bearer", new string[] { } }

            });

        }

    }

}

编辑


如果将 Authorization 标头定义为参数,Swagger UI 将拒绝发送该标头。因此,更好的选择可能是在 SwaggerGen 服务配置中创建安全定义(通常在 Startup.ConfigureServices 中):


public void ConfigureServices(IServiceCollection services)

{

    // Service configuration

    services.AddSwaggerGen(c =>

    {

        // Configure Swagger

        // "Bearer" is the name for this definition. Any other name could be used

        c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme

            {

                Description = "Use bearer token to authorize",

                Type = SecuritySchemeType.Http,

                Scheme = "bearer",

                BearerFormat = "JWT"

            });

    }

}

然后添加安全要求以及对操作定义的引用:


public class AddAuthorizationHeaderOperationHeader : IOperationFilter

{

    public void Apply(OpenApiOperation operation, OperationFilterContext context)

    {

        var actionMetadata = context.ApiDescription.ActionDescriptor.EndpointMetadata;

        var isAuthorized = actionMetadata.Any(metadataItem => metadataItem is AuthorizeAttribute);

        var allowAnonymous = actionMetadata.Any(metadataItem => metadataItem is AllowAnonymousAttribute);


        if (!isAuthorized || allowAnonymous)

        {

            return;

        }

        if (operation.Parameters == null)

            operation.Parameters = new List<OpenApiParameter>();


        operation.Security = new List<OpenApiSecurityRequirement>();


        //Add JWT bearer type

        operation.Security.Add(new OpenApiSecurityRequirement

            {

                {

                    new OpenApiSecurityScheme

                    {                            

                        Reference = new OpenApiReference

                        {                               

                            Type = ReferenceType.SecurityScheme,

                            // Definition name. 

                            // Should exactly match the one given in the service configuration

                            Id = "Bearer"

                        }

                    }, new string[0]

                }

            }

        );

    }

}


查看完整回答
反对 回复 2023-08-13
?
MM们

TA贡献1886条经验 获得超2个赞

请按照以下步骤使用正确的挂锁来实施 Swagger -


步骤1


添加一个类并通过接口继承该类IOperationFilter。之后,实现接口Apply的方法定义IOperationFilter。


要实现Apply方法,您需要两个类型为OpenApiOperation和的参数OpenApiOperation。


public class AddSwaggerService : IOperationFilter

    {     


        public void Apply(OpenApiOperation operation, OperationFilterContext context)

        {

            var actionMetadata = context.ApiDescription.ActionDescriptor.EndpointMetadata;

            var isAuthorized = actionMetadata.Any(metadataItem => metadataItem is AuthorizeAttribute);

            var allowAnonymous = actionMetadata.Any(metadataItem => metadataItem is AllowAnonymousAttribute);


            if (!isAuthorized || allowAnonymous)

            {

                return;

            }

            if (operation.Parameters == null)

                operation.Parameters = new List<OpenApiParameter>();


            operation.Security = new List<OpenApiSecurityRequirement>();


            

            var security = new OpenApiSecurityRequirement

            {

                {

                    new OpenApiSecurityScheme

                    {

                        Reference = new OpenApiReference

                        {

                            Type = ReferenceType.SecurityScheme,                            

                            Id = "Bearer"

                        }

                    }, new List<string>()

                }

            };

            //add security in here

            operation.Security.Add(security);

        }

第2步


添加swagger Generation Service在ConfigureServices方法中Startup.cs。在此服务中,您需要添加我们在步骤 1 中实现的以下行。


c.OperationFilter<AddSwaggerService>();


 public void ConfigureServices(IServiceCollection services)

        {


//.........other Services.........

//.........other Services.........

//.........other Services.........


services.AddSwaggerGen(c =>

                c.SwaggerDoc(AppConstantKeys.APIName, new OpenApiInfo { Title = "title", Version = "APIVersion" });


                c.OperationFilter<AddSwaggerService>();

                c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme

                {

                    Description ="SwaggerShortDescription",

                    Name = "HeaderName",

                    In = ParameterLocation.Header,

                    Type = SecuritySchemeType.ApiKey,


                });

            });


//.........other Services.........

//.........other Services.........

//.........other Services.........


}

Step-3 在中间件管道中添加 swagger。


public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

        {

//.........other middlewares.........

//.........other middlewares.........

//.........other middlewares.........

//.........other middlewares.........



            app.UseSwagger();

            app.UseSwaggerUI(c =>

            {

                c.SwaggerEndpoint("/swagger/v1/swagger.json", "SwaggerUIName");

                c.DocumentTitle = "SwaggerUITitle";

                c.DocExpansion(DocExpansion.None);

                c.RoutePrefix = string.Empty;

            });


//.........other middlewares.........

//.........other middlewares.........

//.........other middlewares.........

//.........other middlewares.........



}



步骤4


构建并运行。

https://img1.sycdn.imooc.com//64d888930001b67e14490230.jpg

查看完整回答
反对 回复 2023-08-13
  • 3 回答
  • 0 关注
  • 129 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信