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

ASP.NET Core 6 Web API自定义特性传参 HubFilter执行异常问题

问题根因

你遇到的两个问题核心是混淆了SignalR全局Hub过滤器和MVC特性过滤器的运行逻辑:

  • 调用hubOptions.AddFilter<T>()是全局注册过滤器,注册后所有Hub的所有方法调用都会触发该过滤器,不会自动判断方法/类是否标注了对应特性,所以才会出现没打标记也执行的情况。
  • 你额外封装的RTProAuthorizationHubFilter属于多余的套娃层,全局注册时DI容器无法自动解析构造函数里的bool isAuthorization参数,同时你也没有在过滤器逻辑里判断特性标记,既导致参数传不进去,也导致过滤器全量执行。
修复方案

不需要保留RTProAuthorizationHubFilter包装类,直接调整RTProAuthorizationHubContext的逻辑,在过滤器内部自行判断当前调用的类/方法是否标记了特性,再决定是否执行授权逻辑即可。

第一步:修改RTProAuthorizationHubContext代码

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
public class RTProAuthorizationHubContext : AuthorizeAttribute, IHubFilter
{
    private readonly ISecurityService _securityService;
    private readonly IRTProAuthenticationService _rTProAuthenticationService;
    private readonly IUnitOfWork _unitOfWork;
    private readonly IOptions<AuthenticationSettingsInfo> _authenticationSettings;
    // 公开属性用于读取标记时传入的参数
    public bool IsAuthorization { get; }

    // 注意:DI注入的参数放前面,自定义非注入参数放最后并设置默认值,避免DI解析报错
    public RTProAuthorizationHubContext(
        ISecurityService securityService,
        IRTProAuthenticationService rTProAuthenticationService,
        IUnitOfWork unitOfWork,
        IOptions<AuthenticationSettingsInfo> authenticationSettings,
        bool isAuthorization = true
    )
    {
        IsAuthorization = isAuthorization;
        _rTProAuthenticationService = rTProAuthenticationService;
        _authenticationSettings = authenticationSettings;
        _unitOfWork = unitOfWork;
        _securityService = securityService;
    }

    public async ValueTask<object> InvokeMethodAsync(
        HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object>> next)
    {
        // 先查找当前执行方法上的特性,找不到再查找Hub类上的特性
        var hubType = invocationContext.Hub.GetType();
        var methodInfo = hubType.GetMethod(invocationContext.HubMethodName);
        var authAttr = methodInfo?.GetCustomAttribute<RTProAuthorizationHubContext>() 
                       ?? hubType.GetCustomAttribute<RTProAuthorizationHubContext>();

        // 没有标记特性直接放行,不执行授权逻辑
        if (authAttr == null)
        {
            return await next(invocationContext);
        }

        // 此处写你的授权逻辑,通过authAttr.IsAuthorization即可拿到标记时传入的参数值
        // ...... 原有授权代码
        
        return await next(invocationContext);
    }
}

第二步:修改Program.cs中的SignalR注册

直接注册调整后的RTProAuthorizationHubContext即可,不需要注册之前的包装类:

builder.Services.AddSignalR(hubOptions =>
{
    hubOptions.EnableDetailedErrors = true;
    hubOptions.KeepAliveInterval = TimeSpan.FromMinutes(1);
    hubOptions.AddFilter<RTProAuthorizationHubContext>();
});

第三步:在Hub类/方法上标记特性传参

直接在需要控制授权的类或方法上标记特性,传入isAuthorization参数即可:

// 类上标记,该Hub下所有方法默认开启授权
[RTProAuthorizationHubContext]
public class BusinessHub : Hub
{
    // 单独标记该方法,关闭授权校验
    [RTProAuthorizationHubContext(isAuthorization: false)]
    public async Task PublicAccessMethod()
    {
        // 公开接口逻辑
    }

    // 未单独标记的方法沿用类上的配置,开启授权校验
    public async Task ProtectedMethod()
    {
        // 需授权接口逻辑
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 06:15:43