基于MVC简单的权限管理
项目中,我们常会遇到权限管理的相关业务,基于MVC的实现原理(自定义HttpModule(UrlRoutingModule)和HttpHandler(MvcHandler)),我们可以通过自定义AuthorizeAttribute来实现对请求的过滤。AuthorizeAttribute继承自 FilterAttribute,IAuthorizationFilter;
1. AuthorizeAttribute 成员结构如下:

1 // 摘要: 2 // 表示一个特性,该特性用于限制调用方对操作方法的访问。 3 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] 4 public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter 5 { 6 // 摘要: 7 // 初始化 System.Web.Mvc.AuthorizeAttribute 类的新实例。 8 public AuthorizeAttribute(); 9 10 // 摘要: 11 // 获取或设置用户角色。 12 // 13 // 返回结果: 14 // 用户角色。 15 public string Roles { get; set; } 16 // 17 // 摘要: 18 // 获取此特性的唯一标识符。 19 // 20 // 返回结果: 21 // 此特性的唯一标识符。 22 public override object TypeId { get; } 23 // 24 // 摘要: 25 // 获取或设置授权用户。 26 // 27 // 返回结果: 28 // 授权用户。 29 public string Users { get; set; } 30 31 // 摘要: 32 // 重写时,提供一个入口点用于进行自定义授权检查。 33 // 34 // 参数: 35 // httpContext: 36 // HTTP 上下文,它封装有关单个 HTTP 请求的所有 HTTP 特定的信息。 37 // 38 // 返回结果: 39 // 如果用户已经过授权,则为 true;否则为 false。 40 // 41 // 异常: 42 // System.ArgumentNullException: 43 // httpContext 参数为 null。 44 protected virtual bool AuthorizeCore(HttpContextBase httpContext); 45 // 46 // 摘要: 47 // 处理未能授权的 HTTP 请求。 48 // 49 // 参数: 50 // filterContext: 51 // 封装有关使用 System.Web.Mvc.AuthorizeAttribute 的信息。filterContext 对象包括控制器、HTTP 上下文、请求上下文、操作结果和路由数据。 52 protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext); 53 // 54 // 摘要: 55 // 在过程请求授权时调用。 56 // 57 // 参数: 58 // filterContext: 59 // 筛选器上下文,它封装有关使用 System.Web.Mvc.AuthorizeAttribute 的信息。 60 // 61 // 异常: 62 // System.ArgumentNullException: 63 // filterContext 参数为 null。 64 public virtual void OnAuthorization(AuthorizationContext filterContext); 65 // 66 // 摘要: 67 // 在缓存模块请求授权时调用。 68 // 69 // 参数: 70 // httpContext: 71 // HTTP 上下文,它封装有关单个 HTTP 请求的所有 HTTP 特定的信息。 72 // 73 // 返回结果: 74 // 对验证状态的引用。 75 // 76 // 异常: 77 // System.ArgumentNullException: 78 // httpContext 参数为 null。 79 protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext); 80 }
2.我们通过自定义的SimpleAuthorizeAttribute 继承AuthorizeAttribute,并对入口授权方法AuthorizeCore进行重写。
(1)我们先定义平台角色

1 /// <summary> 2 /// 人员角色枚举值 3 /// </summary> 4 [Flags] 5 [Serializable] 6 public enum PersonRole 7 { 8 /// <summary> 9 /// 10 /// </summary> 11 None = 0, 12 /// <summary> 13 /// 普通人员 14 /// </summary> 15 Default = 1, 16 /// <summary> 17 /// 超级管理员 18 /// </summary> 19 Administrator = 8 20 }
(2)重写

1 public class SimpleAuthorizeAttribute : AuthorizeAttribute 2 { /// <summary> 3 /// 人员角色枚举 4 /// </summary> 5 /// <returns>用户角色。</returns> 6 new PersonRole Roles { get; set; } 7 8 /// <summary> 9 /// Initializes a new instance of the <see cref="SimpleAuthorizeAttribute"/> class. 10 /// </summary> 11 /// <param name="role">The role.</param> 12 public SimpleAuthorizeAttribute(PersonRole role) 13 { 14 this.Roles = role; 15 } 16 17 /// <summary> 18 /// 重写时,提供一个入口点用于进行自定义授权检查。 19 /// </summary> 20 /// <param name="httpContext">HTTP 上下文,它封装有关单个 HTTP 请求的所有 HTTP 特定的信息。</param> 21 /// <returns> 22 /// 如果用户已经过授权,则为 true;否则为 false。 23 /// </returns> 24 /// <exception cref="System.ArgumentNullException">HttpContext</exception> 25 protected override bool AuthorizeCore(HttpContextBase httpContext) 26 { 27 if (httpContext == null) 28 throw new ArgumentNullException("HttpContext"); 29 30 //是否验证了用户 31 if (!httpContext.User.Identity.IsAuthenticated) 32 return false; 33 34 var role = this.GetPersonRole(httpContext.User.Identity.Name); 35 36 if (Roles.HasFlag(role)) 37 return true; 38 39 return false; 40 } 41 42 /// <summary> 43 /// 在过程请求授权时调用。 44 /// </summary> 45 /// <param name="filterContext">筛选器上下文,它封装有关使用 <see cref="T:System.Web.Mvc.AuthorizeAttribute" /> 的信息。</param> 46 public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext) 47 { 48 string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName; 49 string actionName = filterContext.ActionDescriptor.ActionName; 50 51 base.OnAuthorization(filterContext); 52 } 53 54 /// <summary> 55 /// 获取当前登录用户的角色 56 /// </summary> 57 /// <param name="userName">人员的登录用户名</param> 58 /// <returns> 59 /// 角色 60 /// </returns> 61 PersonRole GetPersonRole(string userName) 62 { 63 //此处调用根据用户名获取用户角色的服务 64 return PersonRole.Administrator; 65 } 66 }
重写后,我们只需要在方法体头或者控制器头加上该特性即可,例如

[SimpleAuthorize(PersonRole.Administrator)] public class ManageController : Controller
即对该控制器进行了权限的控制。
此文只适合固定角色和固定权限的方式来控制,业务逻辑比较简单,如果要实现复杂的业务逻辑,则需要动态的配置角色和方法的关联,即角色拥有方法集合,用户拥有角色的模式去控制。