Masoud DaneshPour
Masoud DaneshPour

Reputation: 126

How to prevent executing of specific custom action filter

I have an custom action filter like this :

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

I add this to FilterConfig for all the actions.but I need some actions work without it. for now I use something like this :

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);
    }
}

and the usage :

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

but how can build something like [AllowAnonymous] attribute

best regards

Upvotes: 4

Views: 2329

Answers (3)

donprecious iyeritufu
donprecious iyeritufu

Reputation: 169

To build something like [AllowAnonymous] filter, you can inherit IAllowAnonymousFilter or whatever filter of your choice, then you have to make validation in other filters eg custom authorization filter, if context.filter is IAllowAnonymousFilter

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

example

 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 
}

i choose to leave IOrderedFilter in the code because you may want to change the order of execution on the filter, since you will want this to be executed first

you can now use it like this

 [AuthorizeAllAccess]
    public class UsersController : ControllerBase
    {  

     /// other action method 


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

  }


  }

Upvotes: 0

NightOwl888
NightOwl888

Reputation: 56869

You simply need to make another attribute and use .NET reflection to check for its existence.

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);
}

And then make a custom attribute to decorate your actions/controllers with.

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

Usage

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

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

In general, it is best not to use ActionFilterAttribute if you are using dependency injection, since attributes should contain no behavior as in this answer. You should also consider using an authorization filter (or AuthorizationAttribute-inherited class) rather than an action filter for security checks, since it is done earlier in the pipeline.

Upvotes: 5

Darin Dimitrov
Darin Dimitrov

Reputation: 1038930

but how can build something like [AllowAnonymous] attribute

Quite easy actually:

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

and then in your filter account for it:

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
        }
    }
}

Now all that's left is decorate:

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

Upvotes: 5

Related Questions