In other words, is this a really stupid idea?
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorizeActionAttribute : Auth
If you want to do this, taking Levi's recommendation into account, the answer is as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
namespace MvcApplication1.Extension.Attribute
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorizeActionAttribute : AuthorizeAttribute
{
///
/// Called when a process requests authorization.
///
/// The filter context, which encapsulates information for using .
/// The parameter is null.
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
// auth failed, redirect to login page
filterContext.Result = new HttpUnauthorizedResult();
return;
}
// these values combined are our roleName
string roleName = GetRoleName(filterContext);
if (!filterContext.HttpContext.User.IsInRole(roleName))
{
filterContext.Controller.TempData.Add("RedirectReason", "You are not authorized to access this page.");
filterContext.Result = new RedirectResult("~/Error/Unauthorized");
return;
}
//
base.OnAuthorization(filterContext);
}
///
/// Gets the name of the role. Theorectical construct that illustrates a problem with the
/// area name. RouteData is apparently insecure, but the area name is available there.
///
/// The filter context.
/// The version.
///
string GetRoleName(AuthorizationContext filterContext)
{
//
var verb = filterContext.HttpContext.Request.HttpMethod;
// recommended way to access controller and action names
var controllerFullName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerType.FullName;
var actionName = filterContext.ActionDescriptor.ActionName;
return String.Format("{0}.{1}-{2}", controllerFullName, actionName, verb);
}
}
}
I did not want to provide a HttpUnauthorizedResult in the case of a user not being in role, because the result is to send the user to the login page. Considering that they are already logged in, this is extremely confusing to the user.