You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测C#中Action方法传递给函数的非白名单变量?

实现Action方法参数白名单检测的测试函数

需求概述

我们需要编写测试逻辑,验证Action方法中传递给外部函数的变量是否都通过CustomAttribute列入了白名单。如果存在未授权的变量(比如示例中的myVar1)被传递,测试需返回失败(false);仅白名单内的变量(如myParam1)允许传递。

实现方案:基于Roslyn静态分析

利用Roslyn解析代码语法树,直接分析Action方法的结构、特性标记和函数调用行为,是最可靠的静态检测方式。以下是完整的测试实现:

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;

public class ActionWhitelistValidationTests
{
    [Fact]
    public void MyActionMethod_Fails_WhenPassingNonWhitelistedVariables()
    {
        // 1. 定义目标代码(实际项目中可直接加载源码文件或编译单元)
        var targetCode = @"
using System.Threading.Tasks;
using System.Web.Http;

public class SampleController : ApiController
{
    private readonly IDataService _dataService;

    public SampleController(IDataService dataService) => _dataService = dataService;

    [CustomAttribute(""myParam1"")]
    public virtual async Task<IHttpActionResult> MyActionMethod(string myParam1, int myParam2)
    {
        var myVar1 = ""sensitive-value"";
        return await _dataService.GetData(myParam1, myVar1);
    }
}

public interface IDataService
{
    Task<IHttpActionResult> GetData(string allowedParam, string restrictedParam);
}

public class CustomAttribute : Attribute
{
    public CustomAttribute(string whitelistedParam) => ParamName = whitelistedParam;
    public string ParamName { get; }
}";

        // 2. 构建语法树与编译环境
        var syntaxTree = CSharpSyntaxTree.ParseText(targetCode);
        var compilation = CSharpCompilation.Create("WhitelistTestCompilation")
            .AddReferences(
                MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Attribute).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Task).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(IHttpActionResult).Assembly.Location))
            .AddSyntaxTrees(syntaxTree);

        // 3. 定位目标Action方法的语法节点
        var targetMethod = syntaxTree.GetRoot()
            .DescendantNodes()
            .OfType<MethodDeclarationSyntax>()
            .First(m => m.Identifier.Text == "MyActionMethod");

        // 4. 提取CustomAttribute标记的白名单参数
        var whitelistedParams = targetMethod.AttributeLists
            .SelectMany(list => list.Attributes)
            .Where(attr => attr.Name.ToString() == "CustomAttribute")
            .SelectMany(attr => attr.ArgumentList.Arguments)
            .Select(arg => arg.Expression.ToString().Trim('"'))
            .ToList();

        // 5. 收集所有对外函数调用的参数
        var invokedArguments = targetMethod.DescendantNodes()
            .OfType<InvocationExpressionSyntax>()
            .SelectMany(invocation => invocation.ArgumentList.Arguments)
            .Select(arg => arg.Expression.ToString())
            .ToList();

        // 6. 筛选出未授权的传递变量
        var actionParamNames = targetMethod.ParameterList.Parameters.Select(p => p.Identifier.Text).ToList();
        var unauthorizedArguments = invokedArguments
            .Where(arg => 
                // 两种违规情况:1. Action参数但不在白名单;2. 非Action参数(如局部变量)
                (actionParamNames.Contains(arg) && !whitelistedParams.Contains(arg)) ||
                !actionParamNames.Contains(arg))
            .Distinct()
            .ToList();

        // 7. 断言:无未授权变量则测试通过,否则失败
        Assert.Empty(unauthorizedArguments);
    }
}

代码说明

  1. 语法树解析:通过Roslyn将目标代码解析为语法树,方便后续分析方法结构和调用逻辑
  2. 白名单提取:从Action方法的CustomAttribute中提取允许传递的参数名
  3. 调用参数收集:遍历方法内所有函数调用,记录传递的变量名称
  4. 违规检测:对比传递的变量,判断是否属于未授权的情况(局部变量或未标记的Action参数)
  5. 结果断言:如果存在违规变量,Assert.Empty会触发测试失败,符合需求

示例验证

在示例代码中:

  • myParam1在白名单内,传递给GetData是合法的
  • myVar1是局部变量,未被CustomAttribute标记,属于违规传递,测试会失败(返回false)

内容的提问来源于stack exchange,提问作者Mr. Flibble

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 13:07:48