1

我有一个授权过滤器可应用于所有控制器的操作,以保护应用程序的端点(例如CustomAuthorizationFilter : IResourceFilter, IFilterMetadata

可以startup.cs像这样添加此自定义过滤器:

 services.AddControllers(o =>
            {
                o.Filters.Add<CustomAuthorizationFilter>();
                //other stuff here...
            });

对于我的用例,我想确保 100% 使用此过滤器保护所有 API(及其控制器),换句话说,我想确保其类中的MyApp.API.Server .csproj项目引用.startup.csCustomAuthorizationFilter

我开始做的是创建一个SecurityAttributeReaderMyApp.API.Server 来解析项目配置并检查此过滤器是否存在:

public class SecurityAttributeReader
{
     public bool AuthorizationFilterExists()
     {
        return false;
     }
}

我的问题我无法找到检索此信息的解决方案。

你能用你的想法挑战我吗:)

谢谢!


所以这是我的问题,不,我正在用我发现与我的案例更相关的解决方案更新帖子:

这个想法是创建一个将在构建时执行的Roslyn 分析器,该分析器将读取 startup.cs 文件以检查是否引用了目标“CustomAuthorizationFilter”:

public class FilterAnalyser : DiagnosticAnalyzer
    {
        private const string DiagnosticId = "AnalyserId";
        private static DiagnosticDescriptor Rule = new DiagnosticDescriptor(
           DiagnosticId,
           "title",
           "message format",
           "category",
           DiagnosticSeverity.Error,
           isEnabledByDefault: true);

        public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }

        public override void Initialize(AnalysisContext context)
        {
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
            context.EnableConcurrentExecution();
            context.RegisterCodeBlockStartAction<SyntaxKind>(cb =>
            {
                bool filterInvocationFound = false;
                Location errorLocation = null;

                // We only care about method bodies.
                if (cb.OwningSymbol.Kind != SymbolKind.Method)return;

                // We only care about methods with parameters.
                IMethodSymbol method = (IMethodSymbol)cb.OwningSymbol;
                if (method.Parameters.IsEmpty)return;

                // we only care about Startup.cs class
                if (method.ContainingType == null || method.ContainingType.Name != "Startup")return;

                cb.RegisterSyntaxNodeAction(ctx =>
                {
                    if (!(ctx.Node is InvocationExpressionSyntax node)) return;
                    if (!(node.Expression is MemberAccessExpressionSyntax expression)) return;

                    if (expression.Parent.Ancestors().Any(c => c.ToString().Contains("CustomAuthorizationFilter")))
                        filterInvocationFound = true;

                }, SyntaxKind.InvocationExpression);

                cb.RegisterCodeBlockEndAction(ctx =>
                {
                    if (!filterInvocationFound )
                    {
                        var diag = Diagnostic.Create(Rule, method.Locations[0]);
                        ctx.ReportDiagnostic(diag);
                    }
                });
            });
        }
    }
4

1 回答 1

0

正如@Kirk Larkin 所说,这很有趣。您可以创建一个CheckAttributesFilter来检查所有操作,但出现了一个新问题,即我们如何确认这CheckAttributesFilter适用于所有操作。

public void OnActionExecuting(ActionExecutingContext context)
    {
        var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
        if (controllerActionDescriptor != null)
        {
            var isDefined = controllerActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true)
                .Any(a => a.GetType().Equals(typeof(CustomAuthorizationFilter)));
        }
    }
于 2020-07-01T03:19:26.457 回答