我有一个授权过滤器可应用于所有控制器的操作,以保护应用程序的端点(例如CustomAuthorizationFilter : IResourceFilter, IFilterMetadata
)
可以startup.cs
像这样添加此自定义过滤器:
services.AddControllers(o =>
{
o.Filters.Add<CustomAuthorizationFilter>();
//other stuff here...
});
对于我的用例,我想确保 100% 使用此过滤器保护所有 API(及其控制器),换句话说,我想确保其类中的MyApp.API.Server
.csproj
项目引用.startup.cs
CustomAuthorizationFilter
我开始做的是创建一个SecurityAttributeReader
类MyApp.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);
}
});
});
}
}