Geeks With Blogs
Brian Schroer Don't Call Me Mort!
Technorati Tags: ,,

 

I'm rewriting a "classic ASP" (that term always makes me laugh - Just 'cause it's old don't make it "classic") application in ASP.NET MVC 2. There's an existing user authorization table in the database, so I want to keep using that for authorization determination.

I created a custom class inheriting from FilterAttribute and implementing IAuthorizationFilter:

   1:  public class DuffAuthorizeAttribute : FilterAttribute, IAuthorizationFilter
   2:  {
   3:      public DuffAuthorizeAttribute(params UserRole[] acceptedRoles)
   4:      {
   5:          _acceptedRoles = acceptedRoles;   
   6:      }
   7:   
   8:      public void OnAuthorization(AuthorizationContext filterContext)
   9:      {
  10:          User currentUser = UserHelper.GetCurrentUser();
  11:   
  12:          if (!currentUser.IsInRole(_acceptedRoles))
  13:              throw new DuffUnauthorizedAccessException();
  14:      }
  15:   
  16:      private readonly UserRole[] _acceptedRoles;
  17:   
  18:      private IUserHelper _userHelper;
  19:      public IUserHelper UserHelper
  20:      {
  21:          get
  22:          {
  23:              if (_userHelper == null)
  24:                  _userHelper = ObjectFactory.Create<UserHelper>();
  25:   
  26:              return _userHelper;
  27:          }
  28:          set { _userHelper = value; }
  29:      }
  30:  }
 

My constructor takes a params list of one or more UserRole enumeration values.  

IAuthorizationFilter only has one method that must be implemented: OnAuthorization. In my implementation, I'm checking whether the current user is in one of the roles supplied to the constructor. (My User.IsInRole method also takes a params list of accepted roles.)

(I wish I could  set my IUserHelper implementation via constructor injection instead of having to resolve it from my IOC container within the attribute class, but I don't think that's possible, since .NET attribute constructor syntax doesn't it.)

Adding authorization for a controller action is as easy as applying the attribute to an action (or it could be applied at the class level to be in effect for all of the controller's actions:

   1:  public class AdministrationController : Controller
   2:  {
   3:      [DuffAuthorize(UserRole.Administrator)]
   4:      public virtual ActionResult AdministerUsers()
   5:      {
   6:          return View();
   7:      }
   8:   
   9:      [DuffAuthorize(UserRole.Administrator, /*or*/ UserRole.AdminAssistant)]
  10:      public virtual ActionResult Reports()
  11:      {
  12:          return View();
  13:      }
  14:  }


In the example above, only users with an "Administrator" role are authorized for the "AdministerUsers" view, and users with either an "Administrator" or "AdminAssistant" role can see the "Reports" view. If users without the required roles try to go to those views, an exception will be thrown.

Posted on Thursday, July 8, 2010 9:54 PM | Back to top


Comments on this post: Implementing a custom ASP.NET MVC authorization filter

# re: Implementing a custom ASP.NET MVC authorization filter
Requesting Gravatar...
You use the [DuffAuthorize(UserRole.Administrator)] but I only see the DuffAuthorizeAttribute being setup. Is this a typo? Also would you mind sharing the code? I'm also moving from a ASP to MVC 2.
Left by Brian on Jul 15, 2010 8:53 PM

# re: Implementing a custom ASP.NET MVC authorization filter
Requesting Gravatar...
I hope I understand your question correctly. The [DuffAuthorize(... lines are using the DuffAuthorizeAttribute class.

By convention, attribute names end with the word "Attribute" to distinguish them from other items in the .NET Framework. However, you do not need to specify the "Attribute" suffix when using attributes in code.

I'll see if I can put together some code to email you this weekend.
Left by Brian Schroer on Jul 16, 2010 4:29 PM

# re: Implementing a custom ASP.NET MVC authorization filter
Requesting Gravatar...
Do you have some code where this is implemented. I do not understand how to implement your code.

I get errors with
UserRole[]
User
IUserHelper
ObjectFactory

Where do I set the roles?
Left by Actual Implementation on Sep 16, 2010 9:23 AM

# re: Implementing a custom ASP.NET MVC authorization filter
Requesting Gravatar...
I used a mix of your solution and the link below.

Apparently it is recommended that you inherit from AuthorizeAttribute rather than FilterAttribute so that it plays nicely with OutputCache attribute. See http://books.google.co.nz/books?id=lFSPoYt9deAC&pg=PA335&lpg=PA335&dq=asp.net+mvc+filter+attribute+OnAuthorization&source=bl&ots=FzIdN_pb7B&sig=-xVT60dw8Zu78Euo6H1UUy_SQxU&hl=en&ei=RAFGTZCoF4-qvQPXtIzMAQ&sa=X&oi=book_result&ct=result&resnum=10&ved=0CGMQ6AEwCQ#v=onepage&q&f=false
Left by masood on Jan 30, 2011 7:27 PM

# re: Implementing a custom ASP.NET MVC authorization filter
Requesting Gravatar...
could you post your full solution and source?
Left by Fred Mastro on Mar 03, 2011 4:28 PM

# re: Implementing a custom ASP.NET MVC authorization filter
Requesting Gravatar...
I had something along the lines of:

public class CustomAuthorizationAttribute : AuthorizeAttribute
{
public CustomAuthorizationAttribute(params UserRole[] validRoles)
{
if (validRoles != null)
AcceptedRoles = validRoles.ToList();
}

public List<UserRole> AcceptedRoles { get; private set; }

protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext.User is CustomPrincipal)
{
CustomPrincipal principal = httpContext.User as CustomPrincipal;
return principal.IsInRole(AcceptedRoles);
}
return base.AuthorizeCore(httpContext);
}

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
UrlHelper urlHelper = new UrlHelper(filterContext.RequestContext);
if (filterContext.HttpContext.Request.IsAjaxRequest())
{

//return Json
JsonResult result = new JsonResult();
result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
filterContext.Result = result;
}
else
{
if (filterContext.HttpContext.User.Identity.IsAuthenticated)
filterContext.Result = new RedirectResult(urlHelper.Action("Unauthorized", "Error"));
else
base.HandleUnauthorizedRequest(filterContext);
}
}
}
Left by masood on Mar 22, 2011 8:32 PM

Your comment:
 (will show your gravatar)


Copyright © Brian Schroer | Powered by: GeeksWithBlogs.net