首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RequireAuthorization和Swashbuckle

RequireAuthorization和Swashbuckle
EN

Stack Overflow用户
提问于 2020-06-17 23:23:07
回答 3查看 222关注 0票数 1

我正在寻找一种方法来确定端点是否需要使用IOperationFilter进行授权(.Net Core3.1)。

如果授权是通过筛选器或显式设置为属性的,则可以在OperationFilterContext context.ApiDescription.ActionDescriptor.FilterDescriptors.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter)context.ApiDescription.CustomAttributes().OfType<AuthorizeAttribute>()中找到它。

但是,如果授权设置为endpoints.MapControllers().RequireAuthorization();,则它既不会出现在筛选器中,也不会出现在属性中,这应该会将AuthorizationAttribute添加到所有端点。如果在这种情况下将auth应用于端点,您对如何捕获有什么想法吗?

EN

回答 3

Stack Overflow用户

发布于 2021-03-10 01:50:30

phwew,我今天能够像这样击败它(swashbuckle 5.63):

  1. 创建一个像这样的新类

代码语言:javascript
复制
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Authorization;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace YourNameSpace
{
   public class SwaggerGlobalAuthFilter : IOperationFilter
   {
      public void Apply( OpenApiOperation operation, OperationFilterContext context )
      {
         context.ApiDescription.TryGetMethodInfo( out MethodInfo methodInfo );

         if ( methodInfo == null )
         {
            return;
         }

         var hasAllowAnonymousAttribute = false;

         if ( methodInfo.MemberType == MemberTypes.Method )
         {
            // NOTE: Check the controller or the method itself has AllowAnonymousAttribute attribute
            hasAllowAnonymousAttribute = 
               methodInfo.DeclaringType.GetCustomAttributes( true ).OfType<AllowAnonymousAttribute>().Any() ||
               methodInfo.GetCustomAttributes( true ).OfType<AllowAnonymousAttribute>().Any();
         }

         if ( hasAllowAnonymousAttribute )
         {
            return;
         }

         // NOTE: This adds the "Padlock" icon to the endpoint in swagger, 
         //       we can also pass through the names of the policies in the List<string>()
         //       which will indicate which permission you require.
         operation.Security = new List<OpenApiSecurityRequirement>
         {
            new OpenApiSecurityRequirement()
            {
               {
                  new OpenApiSecurityScheme
                  {
                     Reference = new OpenApiReference
                     {
                        Type = ReferenceType.SecurityScheme,
                        Id = "oauth2"  // note this 'Id' matches the name 'oauth2' defined in the swagger extensions config section below
                     },
                     Scheme = "oauth2",
                     Name = "Bearer",
                     In = ParameterLocation.Header,
                  },
                  new List<string>()
               }
            }
         };
      }
   }
}

在swagger配置扩展中

代码语言:javascript
复制
            options.AddSecurityDefinition( "oauth2", new OpenApiSecurityScheme
            {
               Type = SecuritySchemeType.OAuth2,
               Flows = new OpenApiOAuthFlows
               {
                  Implicit = new OpenApiOAuthFlow
                  {
                    //_swaggerSettings is a custom settings object of our own
                     AuthorizationUrl = new Uri( _swaggerSettings.AuthorizationUrl ),
                     Scopes = _swaggerSettings.Scopes
                  }
               }
            } );
            options.OperationFilter<SwaggerGlobalAuthFilter>();

由文档、其他SO和反编译的内置SecurityRequirementsOperationFilter代码组合而成

afaik,它正在为所有路由的端点定义全局身份验证设置,控制器或端点上显式具有AllowAnonymousAttribute的端点除外。正如您最初的问题所暗示的那样,在设置路由时使用扩展RequireAuthorization()隐式地将该属性放在所有端点上,并且检测到Authorize属性的内置SecurityRequirementsOperationFilter无法获取该属性。由于您的路由设置实际上是将Authorize放在每个控制器/路由上,因此,似乎像这样设置一个排除AllowAnonymous的默认全局过滤器将与您在管道中配置的内容保持一致。

我怀疑可能有一种更“内置”的方式来做这件事,但我找不到它。

票数 2
EN

Stack Overflow用户

发布于 2022-01-10 14:35:47

显然,这在NSwag repo上也是一个开放的问题(对于像我这样的人来说,他们也有同样的问题,但使用的是NSwag,而不是Swashbuckle):

https://github.com/RicoSuter/NSwag/issues/2817

这里还有另一个解决问题的例子(不仅是安全需求,还有它的范围)。

票数 0
EN

Stack Overflow用户

发布于 2022-02-14 16:42:13

我知道这个问题已经有很长一段时间了。

但我也面临着类似的问题,根据GitHub here中的一个问题的建议,我设法使用IOperationFilter的这个实现解决了这个问题(现在工作得很棒):

代码语言:javascript
复制
    public class AuthorizeCheckOperationFilter : IOperationFilter
    {
        private readonly EndpointDataSource _endpointDataSource;

        public AuthorizeCheckOperationFilter(EndpointDataSource endpointDataSource)
        {
            _endpointDataSource = endpointDataSource;
        }


        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            var descriptor = _endpointDataSource.Endpoints.FirstOrDefault(x =>
                x.Metadata.GetMetadata<ControllerActionDescriptor>() == context.ApiDescription.ActionDescriptor);
            
            var hasAuthorize = descriptor.Metadata.GetMetadata<AuthorizeAttribute>()!=null;

            var allowAnon = descriptor.Metadata.GetMetadata<AllowAnonymousAttribute>() != null;

            if (!hasAuthorize || allowAnon) return;

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

            operation.Security = new List<OpenApiSecurityRequirement>
            {
                new()
                {
                    [
                        new OpenApiSecurityScheme {Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id = "oauth2"}
                        }
                    ] = new[] {"api1"}
                }
            };
        }
    }

这期杂志这样写道:

ControllerActionDescriptor.EndpointMetadata仅反映在控制器操作上发现的元数据。通过端点API配置的任何元数据都不会在此处显示。这主要是我们将其记录为基础架构的原因-只是因为它使用起来有点混乱。

您可以使用以下几个选项

a)你可以使用Authorize来装饰你的控制器。这应该允许元数据显示在属性中。

b)您可以通过读取EndpointDataSource来查找元数据。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62432556

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档