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

ASP.NET Core 2.0 MVC:结合依赖注入用IControllerModelConvention配置授权过滤器

没问题,这个需求在ASP.NET Core 2.0 MVC里完全可以通过IControllerModelConvention结合依赖注入优雅实现,我给你一步步捋清楚:

1. 先定义支持依赖注入的授权过滤器

首先你需要把两种授权过滤器定义成支持构造函数注入的类型,这样它们就能获取到你需要的依赖服务了。比如:

// 给Identity前缀控制器用的专属授权过滤器
public class IdentityAuthorizeFilter : IAuthorizationFilter
{
    private readonly IIdentityAuthService _identityAuthService;

    // 通过构造函数注入依赖的服务
    public IdentityAuthorizeFilter(IIdentityAuthService identityAuthService)
    {
        _identityAuthService = identityAuthService;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        // 在这里实现你的Identity专属授权逻辑
        // 比如验证特定的身份凭证、权限规则等
    }
}

// 给其余控制器用的默认授权过滤器
public class DefaultAuthorizeFilter : IAuthorizationFilter
{
    private readonly IDefaultAuthService _defaultAuthService;

    public DefaultAuthorizeFilter(IDefaultAuthService defaultAuthService)
    {
        _defaultAuthService = defaultAuthService;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        // 在这里实现通用的授权逻辑
    }
}
2. 实现自定义的IControllerModelConvention

接下来创建一个自定义的约定类,用来根据控制器名称前缀批量添加对应的授权过滤器。这里关键是用ServiceFilterAttribute,它能让MVC自动从依赖注入容器中解析过滤器实例,而不是手动new(手动new的话没法注入依赖):

public class ControllerAuthorizationConvention : IControllerModelConvention
{
    public void Apply(ControllerModel controllerModel)
    {
        // 判断控制器名称是否以"Identity"开头(忽略大小写,你可以根据实际需求调整)
        if (controllerModel.ControllerName.StartsWith("Identity", StringComparison.OrdinalIgnoreCase))
        {
            // 添加Identity专属过滤器,用ServiceFilter让DI容器解析实例
            controllerModel.Filters.Add(new ServiceFilterAttribute(typeof(IdentityAuthorizeFilter)));
        }
        else
        {
            // 添加默认授权过滤器
            controllerModel.Filters.Add(new ServiceFilterAttribute(typeof(DefaultAuthorizeFilter)));
        }
    }
}
3. 在Startup中注册服务和约定

最后在Startup.cs的ConfigureServices方法里,把过滤器和约定都注册到DI容器和MVC配置中:

public void ConfigureServices(IServiceCollection services)
{
    // 把两个授权过滤器注册为Scoped服务(也可以根据需求用Transient/Singleton)
    services.AddScoped<IdentityAuthorizeFilter>();
    services.AddScoped<DefaultAuthorizeFilter>();

    // 注册自定义的控制器约定到MVC选项中
    services.AddMvc(options =>
    {
        options.Conventions.Add(new ControllerAuthorizationConvention());
    });

    // 别忘了注册过滤器依赖的其他服务(比如上面示例中的IIdentityAuthService)
    services.AddScoped<IIdentityAuthService, IdentityAuthService>();
    services.AddScoped<IDefaultAuthService, DefaultAuthService>();
}

关键说明

  • 使用ServiceFilterAttribute是核心:它会告知MVC从DI容器中获取指定类型的过滤器实例,这样过滤器构造函数中的依赖就能被正确注入。如果直接new过滤器对象,依赖注入就失效了。
  • 控制器名称判断:这里是基于控制器类的名称(比如IdentityUserController的ControllerName是IdentityUser),如果你的需求是基于路由前缀而不是控制器名称,可以修改Apply方法里的判断逻辑,比如检查controllerModel.Selectors中的路由模板。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:47:13