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

如何通过TypeFilterAttribute向IAsyncAuthorizationFilter正确传参

问题根因

两次代码抛出相同异常的核心原因是TypeFilterAttribute基类的构造参数传错了:
TypeFilterAttribute的构造函数需要传入实际执行过滤逻辑的过滤器实现类型,但你两次都传入了特性类自身的类型typeof(SimpleAuthorizeServiceAttribute),导致框架尝试创建特性类本身的实例作为过滤器,同时用你赋值的Arguments(仅包含一个PermissionData对象)去匹配特性类的构造函数。你的特性类构造函数需要的是(string, string, AccessType)或者params string[]参数,和Arguments里的参数完全不匹配,自然会抛出找不到合适构造函数的异常。

正确实现代码

你不需要改成弱类型的字符串传参,修正基类传入的类型即可保留强类型参数的优势,完整实现如下:

// 权限参数实体、访问枚举如果已经在项目中定义,无需重复编写
public class PermissionData
{
    public string Service { get; set; }
    public string Context { get; set; }
    public AccessType Access { get; set; }

    public PermissionData(string service, string context, AccessType access)
    {
        Service = service;
        Context = context;
        Access = access;
    }
}

public enum AccessType
{
    Read,
    Write,
    Delete
}

public class SimpleAuthorizeServiceAttribute : TypeFilterAttribute
{
    // *核心修正*:base构造传入真正的过滤器实现类型,而非特性自身类型
    public SimpleAuthorizeServiceAttribute(string service, string context, AccessType access) 
        : base(typeof(SimpleAuthorizeServiceFilter))
    {
        // 按过滤器构造函数的参数顺序,传入自定义参数
        Arguments = new object[] { new PermissionData(service, context, access) };
    }

    private class SimpleAuthorizeServiceFilter : IAsyncAuthorizationFilter
    {
        private readonly PermissionData _permissionData;

        // 构造函数支持两类参数:
        // 1. 你在Arguments中传入的自定义参数
        // 2. DI容器中注册的任意服务,框架会自动注入,不需要手动传入Arguments
        public SimpleAuthorizeServiceFilter(PermissionData permissionData)
        {
            _permissionData = permissionData;
        }

        public Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            // 编写实际授权判断逻辑
            var allowAccess = _permissionData.Service != null;
            if (!allowAccess)
            {
                context.Result = new ForbidResult();
            }
            return Task.CompletedTask;
        }
    }
}
使用方式

直接在控制器Action或者控制器类上标注特性即可,支持强类型枚举传参:

[HttpGet]
[SimpleAuthorizeService("test-service", "test-context", AccessType.Read)]
public async Task<bool> ServiceTest()
{
    bool isAllowed = this.HttpContext.IsUserAllowedToAccess(10, 20, 30);
    return isAllowed;
}
注意事项
  • 不需要使用params string[]做弱类型传参,只要基类构造传入的过滤器类型正确,强类型枚举、自定义对象参数都可以正常传递
  • 过滤器的构造函数除了接收Arguments里传入的自定义参数,还可以直接注入DI容器注册的服务,框架会自动解析依赖,不需要手动传值
  • 如果你的授权逻辑不需要依赖DI注入的服务,也可以直接让特性类实现IAsyncAuthorizationFilter接口,在特性类中直接写授权逻辑,这种方式不需要继承TypeFilterAttribute,但无法自动注入DI服务,灵活性较差

内容的提问来源于stack exchange,提问作者JensB

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 20:51:08