views:

671

answers:

5

Hello,

I wondered if/how I can override the default [Authorize] behavior in ASP.NET MVC. I know that I can create a new Action Filter, make my own attribute and so forth; I am merely interested if I can simply change the [Authorize] behavior and replace its workings with my own code?

Edit: Guys and Girls. I appreciate your input but as I wrote, I am not looking to introduce a new [XYZAuthorize] Attribute. I'm aware of how to do this. I want to keep the [Authorize] notation but just change how it works.

+2  A: 

You can subclass the AuthorizeAttribute filter and put your own logic inside it.

Let's see an example. Let's say you want to always authorize local connections. However, if it is a remote connection, you would like to keep the usual authorization logic.

You could do something like:

public class LocalPermittedAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            return (httpContext.Request.IsLocal || base.AuthorizeCore(httpContext)));
        }
}

Or you could always authorize a certain remote address (your machine, for example).

That's it!

Edit: forgot to mention, you will use it the same as you would use the AuthorizeAttribute filter:

class MyController : Controller
{
    [LocalPermittedAuthorize]
    public ActionResult Fire()
    {
        Missile.Fire(Datetime.Now);
    }
}
Bruno Reis
A: 

I see only 2 ways: overriding AuthorizeAttribute.OnAuthorization method or creating your own authorize attribute from scratch.

1) very easy:

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);

        /// your behavior here
    }
}

2) easy too - just look at ASP.NET MVC source, AuthorizeAttribute.cs file

eu-ge-ne
You should avoid creating an authorize attribute from scratch if you don't want a headache when you will implement caching... the Authorize attribute from ASP.NET MVC deals with this aspect already.
Bruno Reis
+1  A: 

Yes, take a look at the MSDN docs for AuthorizeAttribute: http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute.aspx.

Basically, you can override the OnAuthorization() method and customize the behavior. There are other virtual methods on the attribute as well.

EDIT: As Bruno pointed out, you can override the AuthorizeCore() method. The main difference being that AuthorizeCore() takes an HttpContextBase, while OnAuthorization() takes an AuthorizationContext. An instance of AuthorizationContext provides you with more information, such as the Controller, the RequestContext and the RouteData. It also lets you specify an ActionResult.

AuthorizeCore() is more restricted in the information you can access as well as the result you can return, but if you need to authorize cached data, then your logic needs to handle the case where you don't have any of that extra data (since data is served from the cache before the request is routed through the MVC pipeline).

As always, you need to understand your scenario and the available tools and trade-offs between them.

Brannon
The AuthorizeAttribute does not contain an OnAuthorize method. Do you mean OnAuthorization()? Anyway, you shouldn't change it, unless you want some headache when implementing caching, since it is that one method (OnAuthorization) that deals with it.
Bruno Reis
+1  A: 

It seems you can implement a custom filter as usual (and inherit AuthorizeAttribute if you want), and then create a new ActionInvoker that inherits ControllerActionInvoker and overrides GetFilters. In GetFilters, you call base.GetFilters() to get the list of filters, the iterate through the AuthorizationFilters and replace calls to AuthorizeFilter with calls to your custom filter.

Another potential way is to implement custom membership and role providers, depending on what you're trying to do.

svinto
Why would one need a custom ActionInvoker just for a simple authorization filter?
Bruno Reis
@Bruno: Because there seems to be no other way to replace a framework filter with out own, just to create new ones.
svinto
But... why would one want to *replace* the framework filter? Look my comment to the question. It's a dumb thing to do.
Bruno Reis
@Bruno: Say you have a bunch of already written controllers from some other project/developer/whatever that you either don't want or can't change due to not having the source code. You don't want to use SQL Server to store the user and role data, but something else. And you'd rather not implement the custom membership and role providers, because they are bloated and you are lazy. That's when! It's probably better to create custom providers or create custom (new) attributes, but there might be situations that call for replacing calls to the AuthorizationFilter.
svinto
+2  A: 

Implement your own Role Provider and set your app to use it. Then the Authorize attribute will respect your athorization code.

twk