如何防止执行特定的自定义操作过滤器

时间:2016-01-20 07:02:52

标签: asp.net asp.net-mvc

我有一个这样的自定义动作过滤器:

public class MySecurityTest : ActionFilterAttribut{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        //Do some security tests
        base.OnActionExecuting(filterContext);
    }
}

我将此添加到FilterConfig以执行所有操作。但是如果没有它,我需要一些操作。 现在我使用这样的东西:

public class MySecurityTest : ActionFilterAttribute
{
    public bool CheckRules { get; set; }

    public MySecurityTest(bool checkRules = true)
    {
        CheckRules = checkRules;
    }
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (CheckRules)
        {
            //Do some security tests   
        }
        base.OnActionExecuting(filterContext);
    }
}

和用法:

[MySecurityTest(false)]
public ActionResult Index()
{
   return View();
}

但是如何构建像[AllowAnonymous]属性

这样的东西

最好的问候

3 个答案:

答案 0 :(得分:3)

您只需要创建另一个属性并使用.NET反射来检查它的存在。

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    if (!HasMyIgnoreAttribute(filterContext))
    {
        //Do some security tests   
    }
    base.OnActionExecuting(filterContext);
}

public bool HasMyIgnoreAttribute(ActionDescriptor actionDescriptor)
{
    // Check if the attribute exists on the action method
    bool existsOnMethod = actionDescriptor.IsDefined(typeof(MyIgnoreAttribute), false);

    if (existsOnMethod)
    {
        return true;
    }

    // Check if the attribute exists on the controller
    return actionDescriptor.ControllerDescriptor.IsDefined(typeof(MyIgnoreAttribute), false);
}

然后创建一个自定义属性来装饰你的动作/控制器。

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
public class MyIgnoreAttribute : Attribute
{
}

用法

[MySecurity]
public class MyController
{
    [MyIgnore]
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult About()
    {
        return View();
    }
}

一般情况下,如果使用依赖注入,最好不要使用ActionFilterAttribute,因为should contain no behavior中的属性this answer。您还应该考虑使用authorization filter(或AuthorizationAttribute继承的类)而不是动作过滤器来进行安全检查,因为它是在管道的早期完成的。

答案 1 :(得分:2)

  

但是如何构建像[AllowAnonymous]属性

这样的东西

实际上非常简单:

[AttributeUsage(AttributeTargets.Method)]
public class ExcludeMySecurityAttribute : Attribute
{
}

然后在您的过滤帐户中:

public class MySecurityTest : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.ActionDescriptor.GetCustomAttributes(typeof(ExcludeMySecurityAttribute), true).Any())
        {
            // The controller action is decorated with the exclude attribute
            // so you should probably do nothing here
        }
        else
        {
            // Do your security tests here
        }
    }
}

现在剩下的就是装饰:

[ExcludeMySecurity]
public ActionResult Index()
{
   return View();
}

答案 2 :(得分:0)

要构建类似[AllowAnonymous]过滤器的内容,您可以继承IAllowAnonymousFilter或您选择的任何过滤器,然后您必须在其他过滤器中进行验证,例如,如果context.filter是IAllowAnonymousFilter

 var filters = context.Filters;
            for (var i = 0; i < filters.Count; i++)
            {
                if (filters[i] is IAllowAnonymousFilter)
                {
                    return true;
                }
            }

示例

 public class AuthorizeAllAccessActionFilter : IAuthorizationFilter // or whatever filter 
 you inherit
{
  ...... ....
   public void OnAuthorization(AuthorizationFilterContext context)
    {
        var filters = context.Filters;
        for (var i = 0; i < filters.Count; i++)
        {
            if (filters[i] is IAllowAnonymousFilter) // or AnonymousAccessActionFilter
            {
                return ;
            }
        }


     .... ....
     .....
     ....

    } 

 public class AnonymousAccessActionFilter : IAllowAnonymousFilter, 
 IAuthorizationFilter, IOrderedFilter
{ 
 .... 
 ....
 // do what everver implement you want 
}

我选择将IOrderedFilter保留在代码中,因为您可能希望更改过滤器上的执行顺序,因为您希望先执行

您现在可以像这样使用它

 [AuthorizeAllAccess]
    public class UsersController : ControllerBase
    {  

     /// other action method 


  [AnonymousAccess(Order =  int.MinValue)]
  [HttpGet]
  public async Task<IActionResult> GetUsers() {

  }


  }