views:

53

answers:

2

As a theoretical exercise to help me learn the ins and outs of the membership model with relation to MVC I want to figure out if I can load permissions from an external resource, for the purpose of my prototype I've got a flat file that has a list like so:

Controller1,Method1,Get,Anonymous
Controller1,Method1,Post,User,Administrator
Controller2,Method1,Get,Administrator
Controller2,Method1,Post,Administrator
Controller2,Method2,Get,User,Editor,Administrator
Controller2,Method2,Post,Editor,Administrator

Which I can parse using regular expressions to give me a list of roles that have permissions for each controller/action/verb combination.

I have my controller action:

[CustomAuthorize]
public ActionResult Index()
{
    /* Do stuff */
}

I also have my custom authorization component:

public class CustomAuthorize : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        /* How do I access which Controller/Action/Verb fired this? */
    }
}

In order to be able to determine on the fly which roles have access to this controller/action/verb, I need to be able to determine which controller/action/verb called the CustomAuthorize attribute.

I know that I can add properties to my class like so:

public class CustomAuthorize : AuthorizeAttribute
{
    public string Controller { get; set; }
    public string Action { get; set; }
    public string Verb { get; set; }
}

And then call my attribute using:

[CustomAuthorize(Controller="Home",Action="Index",Verb="Get")]
public ActionResult Index()
{
}

But this seems like a maintenance headache. It would be nice if I could just use [Authorize] and have my CustomAuthorize.AuthorizeCore method determine which controller/action/verb referenced it from within the AuthorizeCore method.

Is this possible? If so can someone point me in the right direction of information about how I would achieve this?

+3  A: 

You might want to look at overriding OnAuthorization instead. It gets an AuthorizationContext parameter which has a reference to the Controller and RouteData. Have a look, though, at what the standard AuthorizeAttribute does, especially with respect to caching. You might find some ideas in an article I wrote on my blog about customizing authorization in MVC.

tvanfosson
I've read your post on customizing authorization. Informative. Looks like your suggestion should do the trick.
Kilhoffer
+1  A: 

Try overriding OnAuthorization instead.

public class TestAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        string controllerName = filterContext.RouteData["controller"];
        string actionName = filterContext.RouteData["action"];
        string verb = filterContext.HttpContext.Request.HttpMethod;

        // .. do your processing
        // if fail...
        filterContext.Result = new HttpUnauthorizedResult();

        base.OnAuthorization(filterContext);
    }
}
Chad Moran
This is a bit dangerous without the caveats regarding caching which tvanfosson alludes to above, though.
Craig Stuntz
It's a shame I can't accept both answers... they're both useful and informative and both do what I'm after.
BenAlabaster
@Craig - As a theoretical exercise though, this gives the information I was after, the first 3 lines of the method is what I was after. I can handle the rest in my AuthorizeCore() method as alluded to by TV's answer.
BenAlabaster