How do I create a custom attribute to extend existing Authorize attribute in MVC?
Asked
Active
Viewed 2.3k times
12
-
Please add more details, what exactly you want to extend? – Mike Chaliy Feb 16 '09 at 18:30
-
for now i just want to be able to redirect to the correct page rather than the default home page. – zsharp Feb 16 '09 at 18:33
-
5You can update your question, so everybody will be able to know what you need. – Mike Chaliy Feb 16 '09 at 19:25
4 Answers
18
Derive your class from AuthorizeAttribute. Override the OnAuthorization method. Add and set up a CacheValidationHandler.
public void CacheValidationHandler( HttpContext context,
object data,
ref HttpValidationStatus validationStatus )
{
validationStatus = OnCacheAuthorization( new HttpContextWrapper( context ) );
}
public override void OnAuthorization( AuthorizationContext filterContext )
{
if (filterContext == null)
{
throw new ArgumentNullException( "filterContext" );
}
if (AuthorizeCore( filterContext.HttpContext ))
{
... your custom code ...
SetCachePolicy( filterContext );
}
else if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
// auth failed, redirect to login page
filterContext.Result = new HttpUnauthorizedResult();
}
else
{
... handle a different case than not authenticated
}
}
protected void SetCachePolicy( AuthorizationContext filterContext )
{
// ** IMPORTANT **
// Since we're performing authorization at the action level, the authorization code runs
// after the output caching module. In the worst case this could allow an authorized user
// to cause the page to be cached, then an unauthorized user would later be served the
// cached page. We work around this by telling proxies not to cache the sensitive page,
// then we hook our custom authorization code into the caching mechanism so that we have
// the final say on whether a page should be served from the cache.
HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
cachePolicy.SetProxyMaxAge( new TimeSpan( 0 ) );
cachePolicy.AddValidationCallback( CacheValidationHandler, null /* data */);
}

tvanfosson
- 524,688
- 99
- 697
- 795
-
How can I make this work with Roles? It works ok now but seems like roles are not working. Also AuthorizeCore keeps returning false even when the user is Authenticated which means SetCachePolicy() never gets executed. – Nick Masao Aug 14 '11 at 20:57
-
@Nick - I've since blogged about improving the cache handling aspects: http://farm-fresh-code.blogspot.com/2011/03/revisiting-custom-authorization-in.html – tvanfosson Aug 14 '11 at 21:01
10
You do not need to extend this attribute, web.config is enough. Please read about forms Element for authentication. Pay your attention on defaultUrl. This is something what you need.
<system.web>
<authentication mode="Forms">
<forms defaultUrl="YourUrlGoesHere"/>
</authentication>
</system.web>

Mike Chaliy
- 25,801
- 18
- 67
- 105
-
-
7Hm, why not to specify all requirments before one will give solution? – Mike Chaliy Feb 16 '09 at 22:13
-
1Noo! This is completely wrong: http://blogs.msdn.com/b/rickandy/archive/2010/08/24/securing-your-mvc-application.aspx – handles Oct 21 '11 at 08:42
-
Uh-oh. If the assertion that is made in that blog entry's opening graph is correct, you should probably cut your losses and delete the answer. – MrBoJangles Jan 28 '13 at 21:42
0
I suggest if you just want to extend the current AuthorizeAttribute and add your own authorization on top of that, instead of overriding OnAuthorization just override AuthorizeCore and add your MyCustomAuthorizationHolds condition to it.
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
// This method must be thread-safe since it is called by the thread-safe OnCacheAuthorization() method.
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (base.AuthorizeCore(httpContext) && MyCustomAuthorizationHolds)
return true;
return false;
}
}

kaptan
- 3,060
- 5
- 34
- 46