基于MVC的web项目最好的权限控制方式我认为是对Action的控制,实现思路记录于此,权限管理分成两个部分授权、认证。
一、授权
1、读取当前项目中的所有需要控制的Action
/// <summary> /// 获取当前程序集内的所有Action /// </summary> /// <returns>当前程序集内的所有Action</returns> /// <remarks>author:lorne date:2016-01-13</remarks> public List<ActionInfo> GetAllAction() { var actions = new List<ActionInfo>(); var assembly = Assembly.GetExecutingAssembly();//获取当前程序集 #region 读取XML获取Action说明 Dictionary<string, string> notes = new Dictionary<string, string>(); try { //读取程序集的XML文件 var doc = new XmlDocument(); doc.Load(Server.MapPath(string.Format("~/bin/{0}.xml", assembly.FullName.Substring(0, assembly.FullName.IndexOf(","))))); var membersInfo = doc.FirstChild["members"]; JArray members = (JArray)JsonConvert.DeserializeObject<JObject>(JsonConvert.SerializeXmlNode(doc.LastChild["members"]))["members"]["member"]; foreach (var item in members) { //以key-value形式存储 notes.Add(item.Value<string>("@name"), item.Value<string>("summary").Trim()); } } catch (Exception) { } #endregion foreach (var type in assembly.GetTypes()) { if (type.BaseType == typeof(Controller))//取出Controller { var methods = type.GetMethods(); foreach (var method in methods) { if (method.ReturnType == typeof(ActionResult) || (method.ReturnType.BaseType != null && method.ReturnType.BaseType == typeof(ActionResult)))//取出Action { //允许匿名访问的不计入 if (method.GetCustomAttributes(typeof(AllowAnonymousAttribute)).Count() == 0) { var info = new ActionInfo(); info.Action = method.Name; info.ActionDesc = notes.ContainsKey(string.Format("M:{0}.{1}.{2}", type.Namespace, type.Name, method.Name)) ? notes[string.Format("M:{0}.{1}.{2}", type.Namespace, type.Name, method.Name)] : ""; info.Controller = type.FullName; info.ControllerDesc = notes.ContainsKey(string.Format("T:{0}.{1}", type.Namespace, type.Name)) ? notes[string.Format("T:{0}.{1}", type.Namespace, type.Name)] : ""; actions.Add(info); } } } } } return actions; }
2、保存授权设置,这个没有具体的实现,应该不会有太大的难度
二、认证
1、使用过滤器(继承ActionFilterAttribute)处理Action请求,重写OnActionExecuting
public override void OnActionExecuting(ActionExecutingContext filterContext) { //获取当前用户所拥有的权限 List<ActionInfo> right = new List<ActionInfo>() { new ActionInfo() { Action = "A1", Controller = "RBAC.Controllers.AController" }, new ActionInfo() { Action = "A2", Controller = "RBAC.Controllers.AController" } }; //白名单 var whiteAction = GetWhiteAction(); //获取用户要请求的页面 ActionInfo context = new ActionInfo() { Action = filterContext.ActionDescriptor.ActionName, Controller = filterContext.Controller.ToString() }; //判断是否有权访问 if (!(whiteAction.Any(r => r.Action.Equals(context.Action, StringComparison.CurrentCultureIgnoreCase) && r.Controller.Equals(context.Controller, StringComparison.CurrentCultureIgnoreCase)) || right.Any(r => r.Action.Equals(context.Action, StringComparison.CurrentCultureIgnoreCase) && r.Controller.Equals(context.Controller, StringComparison.CurrentCultureIgnoreCase)))) { filterContext.HttpContext.Response.Redirect("/Main/Msg"); } }
2、在 Global中注册过滤器
GlobalFilters.Filters.Add(new AuthFilter());
3、给一些不需要授权的Action加上特性[AllowAnonymous],当然也可以自定义其他的特性
[AllowAnonymous] public ActionResult Msg() { return View(); }
由此基本完成,也可以下载源码参考下。
原文:http://www.cnblogs.com/hnlong1/p/5128141.html