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

如何在OnActionExecuting中检测控制器方法是否存在指定特性?

正确检测控制器方法是否包含特定特性(如AllowAnonymous/Authorize)的方法

我来帮你解决这个问题,你之前的两种方法都踩了常见的坑,咱们一步步梳理清楚:

先说说你之前的问题出在哪

  1. 第一种方法的错误:
    你用了Attribute.GetCustomAttribute(context.ActionDescriptor.GetType(), typeof(AuthorizeAttribute)),这里context.ActionDescriptor.GetType()获取的是ActionDescriptor本身的类型(比如ASP.NET Core里的ControllerActionDescriptor),而不是你要检查的控制器Action方法的类型,所以肯定拿不到目标方法上的特性,返回Null是必然的。

  2. 第二种方法的错误:
    MethodBase.GetCurrentMethod()获取的是当前正在执行的OnActionExecuting方法本身,不是你要检测的控制器Action方法。所以就算你拿到特性,也是这个过滤器方法的特性,完全不对;而且当这个方法没有AuthorizeAttribute时,自然会抛出索引越界异常。

正确的实现方式(分ASP.NET Core和传统MVC)

针对ASP.NET Core的情况

在ASP.NET Core中,ActionExecutingContext里的ActionDescriptor如果是控制器的Action,会是ControllerActionDescriptor类型,它直接提供了目标Action的MethodInfo和控制器的ControllerTypeInfo,我们可以用这个来获取特性:

public override void OnActionExecuting(ActionExecutingContext context)
{
    // 先确认当前Action是控制器的Action方法
    if (context.ActionDescriptor is ControllerActionDescriptor actionDescriptor)
    {
        // 检查Action方法上是否存在AllowAnonymous特性
        bool hasAllowAnonymous = actionDescriptor.MethodInfo
            .GetCustomAttributes(typeof(AllowAnonymousAttribute), inherit: true)
            .Any();

        // 检查Action方法上是否存在Authorize特性
        bool hasActionAuthorize = actionDescriptor.MethodInfo
            .GetCustomAttributes(typeof(AuthorizeAttribute), inherit: true)
            .Any();

        // (可选)检查控制器类上是否存在Authorize特性
        bool hasControllerAuthorize = actionDescriptor.ControllerTypeInfo
            .GetCustomAttributes(typeof(AuthorizeAttribute), inherit: true)
            .Any();

        // 根据检测结果执行你的逻辑
        if (hasAllowAnonymous)
        {
            // 比如跳过授权检查
        }
        else if (hasActionAuthorize || hasControllerAuthorize)
        {
            // 执行授权验证逻辑
        }
    }

    base.OnActionExecuting(context);
}

针对传统ASP.NET MVC(非Core)的情况

传统MVC里对应的是ReflectedActionDescriptor,逻辑类似:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    if (filterContext.ActionDescriptor is ReflectedActionDescriptor actionDescriptor)
    {
        bool hasAllowAnonymous = actionDescriptor.MethodInfo
            .GetCustomAttributes(typeof(AllowAnonymousAttribute), true)
            .Any();

        bool hasActionAuthorize = actionDescriptor.MethodInfo
            .GetCustomAttributes(typeof(AuthorizeAttribute), true)
            .Any();

        bool hasControllerAuthorize = actionDescriptor.ControllerType
            .GetCustomAttributes(typeof(AuthorizeAttribute), true)
            .Any();

        // 后续逻辑...
    }

    base.OnActionExecuting(filterContext);
}

几个关键细节

  • 用Any()代替索引访问:这样就算没有对应特性,也不会抛出索引越界异常,直接返回false,更安全。
  • inherit参数的作用:设为true时,会检查继承链上的特性(比如方法继承自父类的特性);如果只需要检查当前方法/控制器本身的特性,设为false即可。
  • 区分方法和控制器的特性:很多时候Authorize特性会加在控制器类上,作用于所有Action,所以如果需要完整的授权逻辑,要同时检查方法和控制器的特性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:40:47