Question

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?

Was it helpful?

Solution

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

OTHER TIPS

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

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

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

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?

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]

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()
    {

    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top