在上一节中提到可以使用AuthorizeAttribute进行权限管理:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17  | 
						        [Authorize]         public ActionResult TestAuthorize()         {              return View();         }         [Authorize(Users="test1,test2")]         public ActionResult TestAuthorize()         {              return View();         }         [Authorize(Roles="Admin")]         public ActionResult TestAuthorize()         {              return View();         }  | 
					
但是通常情况下,网站的权限并不是固定不变的,当新增角色或者角色改变时,只能修改每个Action对应的特性,当项目较大时工作量可想而知。幸运的是我们可以重写AuthorizeAttribute达到自定义的权限管理。新建一个CustomAuthorizeAttribute类,使这个类继承于AuthorizeAttribute。打开AuthorizeAttribute查看下方法说明,我们只需要重写AuthorizeCore和OnAuthorization就能达到我们的目的。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29  | 
						// Summary:         //     When overridden, provides an entry point for custom authorization checks.         //         // Parameters:         //   httpContext:         //     The HTTP context, which encapsulates all HTTP-specific information about         //     an individual HTTP request.         //         // Returns:         //     true if the user is authorized; otherwise, false.         //         // Exceptions:         //   System.ArgumentNullException:         //     The httpContext parameter is null.         protected virtual bool AuthorizeCore(HttpContextBase httpContext); //         // Summary:         //     Called when a process requests authorization.         //         // Parameters:         //   filterContext:         //     The filter context, which encapsulates information for using System.Web.Mvc.AuthorizeAttribute.         //         // Exceptions:         //   System.ArgumentNullException:         //     The filterContext parameter is null.         public virtual void OnAuthorization(AuthorizationContext filterContext);  | 
					
在CustomAuthorizeAttribute中重载AuthorizeCore方法,它的处理逻辑如下:首先判断当前账户是否被认证,如果没有,则返回false;然后获取当前账户的类型,并跟给定的类型进行比较,如果类型相同,则返回true,否则返回false。一般网站中权限管理都会使用权限树,然后将角色的权限保存至数据库或者文件中,本例中我们使用XML文件保存每个Action的角色,这样在用户请求Action时,由XML文件获取Action对应的权限,然后检测账户是否有相应的权限。CustomAuthorizeAttribute类的代码如下:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36  | 
						public class CustomAuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute     {         public new string[] Roles { get; set; }         protected override bool AuthorizeCore(HttpContextBase httpContext)         {             if (httpContext == null) {                 throw new ArgumentNullException("HttpContext");             }             if (!httpContext.User.Identity.IsAuthenticated) {                 return false;             }             if (Roles == null) {                 return true;             }             if (Roles.Length == 0)             {                 return true;             }             if (Roles.Any(httpContext.User.IsInRole))             {                 return true;             }             return false;         }         public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)         {             string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;             string actionName = filterContext.ActionDescriptor.ActionName;             string roles = GetRoles.GetActionRoles(actionName, controllerName);             if (!string.IsNullOrWhiteSpace(roles)) {                 this.Roles = roles.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);             }             base.OnAuthorization(filterContext);         }     }  | 
					
当用户请求一个Action时,会调用OnAuthorization方法,该方法中GetRoles.GetActionRoles(actionName, controllerName);根据Controller和Action去查找当前Action需要具有的角色类型,获得Action的Roles以后,在AuthorizeCore中与用户的角色进行比对Roles.Any(httpContext.User.IsInRole),如果没有相应权限则返回false,程序就会自动跳转到登录页面。
GetRoles为XML解析类,代码如下:
| 
					 1  | 
						
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22  | 
						   public class GetRoles     {         public static string GetActionRoles(string action, string controller) {             XElement rootElement = XElement.Load(HttpContext.Current.Server.MapPath("/")+"ActionRoles.xml");             XElement controllerElement = findElementByAttribute(rootElement, "Controller", controller);             if (controllerElement != null)             {                 XElement actionElement = findElementByAttribute(controllerElement, "Action", action);                 if (actionElement != null)                 {                     return actionElement.Value;                 }             }             return "";         }         public static XElement findElementByAttribute(XElement xElement,string tagName, string attribute)         {             return xElement.Elements(tagName).FirstOrDefault(x => x.Attribute("name").Value.Equals(attribute,StringComparison.OrdinalIgnoreCase));         }     }  | 
					
相应的权限XMl文件:
| 
					 1 2 3 4 5 6 7 8  | 
						<?xml version="1.0" encoding="utf-8" ?> <Roles>     <Controller name="Home">         <Action name="Index"></Action>         <Action name="About">Manager,Admin</Action>         <Action name="Contact">Admin</Action>     </Controller> </Roles>  | 
					
当需求发生变化时,只需要修改XML文件即可
使用时,只需要在FilterConfig中注册该filter
| 
					 1  | 
						filters.Add(new CustomAuthorizeAttribute());  | 
					
当然这只是一个简单的例子,实际应用中会复杂许多,还可能要实现在即的MemberShipProvider和RoleProvider
from:http://www.cnblogs.com/jyan/archive/2012/07/24/2606646.html