zoukankan      html  css  js  c++  java
  • 朴素的标题:MVC中权限管理实践

      基于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;
            }
    View Code

       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");
                }
            }
    View Code

      2、在 Global中注册过滤器

         GlobalFilters.Filters.Add(new AuthFilter());

      3、给一些不需要授权的Action加上特性[AllowAnonymous],当然也可以自定义其他的特性

            [AllowAnonymous]
            public ActionResult Msg()
            {
                return View();
            }

     

      由此基本完成,也可以下载源码参考下

  • 相关阅读:
    LeetCode子集问题
    面试题-求最大字典区间
    链表快速排序
    树的非递归遍历
    快速排序非递归实现
    leetcode217 python3 72ms 存在重复元素
    leetcode121 C++ 12ms 买股票的最佳时机 只能买卖一次
    leetcode1 python3 76ms twoSum 360面试题
    leetcode485 python3 88ms 最大连续1的个数
    leetcode119 C++ 0ms 杨辉三角2
  • 原文地址:https://www.cnblogs.com/hnlong1/p/5128141.html
Copyright © 2011-2022 走看看