12

I made a new action filter (attribute, similar to [Authorize]) which authorizes access to a controller action based on a session value. However, I'm basically decorating all my controller actions with that attribute (with the exception of very few).

So, I thought it would be better to have that Action Filter always executed except in cases where I attach an [ExemptFromAuthorize] attribute to a controller action? (Maybe via inheriting to my own Controller class?)

How can I do this?

1
  • This question is old and in MVC4 there is a new attribute called AllowAnonymous made specifically for this. Commented Aug 6, 2013 at 16:55

7 Answers 7

8

Running with jeef3's answer, I came up with this. It could use more error checking and robustness like multiple delimited actions, but the general idea works.

In your specific case, you could test for the session value and decide to return out of the authorization also.

public class AuthorizeWithExemptionsAttribute : AuthorizeAttribute
{
    public string Exemption { get; set; }
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext.RouteData.GetRequiredString("action") == Exemption)
            return;

        base.OnAuthorization(filterContext);
    }

}

Usage:

[AuthorizeWithExemptions(Roles="admin", ExemptAction="Index")]
public class AdminController : Controller
...
Sign up to request clarification or add additional context in comments.

Comments

7

Check out my article on codeproject -

http://www.codeproject.com/KB/web-security/AuthorizeWithExemptions.aspx

In this article, I'll provide you with a solution for securing ASP.NET MVC application's controllers in a way that all the actions are secured except those you define as unsecure.

snipper from the code:

public override void OnAuthorization(AuthorizationContext filterContext)
{
    ActionDescriptor action = filterContext.ActionDescriptor;
    bool IsUnsecured = action.GetCustomAttributes(
                         typeof(UnsecuredActionAttribute), true).Count() > 0;

    //If doesn't have UnsecuredActionAttribute - then do the authorization
    filterContext.HttpContext.SkipAuthorization = IsUnsecured;

    base.OnAuthorization(filterContext);
}

Comments

6

I understand the question is pretty outdated but anyway.. If you wish to apply filter to all actions just add following lines into Global.asax:

protected void Application_Start()
{
    // your code here and then
    RegisterGlobalFilters(GlobalFilters.Filters);
}    

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new MyActionFilterAttribute());
}

And in action filter you can just check if action has any other attributes in following way:

public void OnActionExecuting(ActionExecutingContext filterContext)
{
    if (filterContext.ActionDescriptor.IsDefined(typeof(AnotherActionAttribute), false))
    {
        // do what you want to do
    }
}

2 Comments

ActionDescriptor does not currently define "IsDefined".
For anyone coming to this for the question in the question title, the first part of this is the actual answer to how to run an action filter on every controller action.
3

Maybe try and add an Except property to your first attribute?

[MyAuthenticate(Exempt="View")]
public class MyController : Controller
{
    public ActionResult Edit()
    {
        // Protected
    }

    public ActionResult View()
    {
        // Accessible by all
    }
}

1 Comment

How would the logic in the action filter work though? (Actually making the "Exempt" work)?
2

You can add the attribute to the class to have it apply to all methods in that class

[Authenticate]
public class AccountController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

I don't know how to exclude a specific method from a class-level attribute. Maybe use a separate controller for unauthenticated requests?

1 Comment

Making separate controllers would spaghetti-ize my code ... excluding specific methods from the class level attribute would be exactly what I need.
2

For anyone reading this in 2013+, MVC4 now supports the use of [AllowAnonymous]

You can put Authorize on the controller, and then Allow Anonymous on any functions you do not want to authorize.

Example:

[Authorize] public class HomeController : Controller {

[AllowAnonymous]
public ActionResult Index()
{

} 

}

Would this work with a custom [MyAuthorize] filter or does it only work with [Authorize]

1 Comment

If you derive your [MyAuthorize] from AuthorizeAttribute, [AllowAnonymous] will work for you to.
1

For anyone reading this in 2013+, MVC4 now supports the use of [AllowAnonymous]

You can put Authorize on the controller, and then Allow Anonymous on any functions you do not want to authorize.

Example:

[Authorize]
public class HomeController : Controller
{

    [AllowAnonymous]
    public ActionResult Index()
    {

    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.