如何给多个子系统设计一个简单通用的权限管理方案?(详细讲解及源代码下载)

 

  前天已发过文章分享了刚完成的一个主数据系统,受到了不少朋友的关注,这篇文章主要是对主数据权限设计方案的讲解,希望对大家有所帮助。源码下载与运行说明请查看分享一个通用强大的主数据管理系统(架构设计讲解及源码下载) 

 

  权限管理一般为分授权验权两大块,另外还有验权测试,这是在系统测试阶段要完成的工作。这里重点要讲的是授权,验权会讲一部分。

 

一、主要数据表设计

 

这是权限分组表,设计它是为了在管理权限时更加清晰,没其它特别的意义。

 

这是权限项表,这个表是重点,其中:

Code是对应系统中的权限码(例如删除用户:delete_user),最终验权的时候是权限这个权限码来获取权限值的。

DisplayStyle是权限项的显示样式,除了CheckBox是简单true/false权限外,TextBox、DropDownList、TreeView这三种都是自己定义数据型权限,也是难点,更是本设计方案的特色,当然还可以扩展其它类型的权限。

JsonDataUrl是支持远程权限值的初始化,JsonDataConst是支持静态权限值的初始化,Json数据格式如下:

 

下面看看添加权限项的界面:

 然后看看授权的界面:

 

这是角色表,每个系统都有自己的多个角色,每个角色都有自己的权限,其中PermissionJsonData就是用于保存权限的。

 

这是用户个人的永久权限表,其中PermissionJsonData就是用于保存权限的。

这是用户个人的临时权限表,其中PermissionJsonData就是用于保存权限的,BeginDate和EndDate保存权限的有效日期。

 

这个表是用于保存用户与角色的关系的,一个用户可以拥有一个或多个角色。

 

二、受权的代码实现

首先,我们需要按需求来定义合理的数据模型(主要给系统的表示层使用的),其中DbModels里放的是和数据表对应的数据模型,ExtendedModels里放的是特别需求扩展的数据模型,JsonModels里放的是Json数据序列化需要的数据模型。其中PermissionDropDownListOption是为DropDownList类型权限设计的,PermissionTreeViewNode是为TreeView类型权限设计的,代码如下:

PermissionDropDownListOption
    [DataContract]
    [Serializable]
    public class PermissionDropDownListOption
    {
        [DataMember]
        public string text { get; set; }

        [DataMember]
        public string value { get; set; }

        [DataMember]
        public bool selected { get; set; }

        public PermissionDropDownListOption()
            : this(string.Empty, string.Empty, false)
        {
        }

        public PermissionDropDownListOption(string text, string value)
            : this(text, value, false)
        {
        }

        public PermissionDropDownListOption(string text, string value, bool selected)
        {
            this.text = text;
            this.value = value;
            this.selected = selected;
        }
    }

 

PermissionTreeViewNode
    [DataContract]
    [Serializable]
    public class PermissionTreeViewNode
    {
        [DataMember]
        public string id { get; set; }

        [DataMember]
        public bool isParent { get; set; }

        [DataMember]
        public string name { get; set; }

        [DataMember]
        public bool @checked { get; set; }

        [DataMember]
        public string icon { get; set; }

        [DataMember]
        public string iconOpen { get; set; }

        [DataMember]
        public string iconClose { get; set; }

        [DataMember]
        public List<PermissionTreeViewNode> childs { get; set; }

        public PermissionTreeViewNode()
            : this(string.Empty, false, string.Empty)
        {
        }

        public PermissionTreeViewNode(string id, bool isParent, string name)
        {
            this.id = id;
            this.isParent = isParent;
            this.name = name;
            this.@checked = false;
            this.icon = string.Empty;
            this.iconOpen = string.Empty;
            this.iconClose = string.Empty;
            this.childs = new List<PermissionTreeViewNode>();
        }
    }

 

写到这,大家先看一下授权的页面,初始化控件和保存权限都算是一个难点,在显示权限控件方面,其实只要获取相应系统的所有权限项,根据类型来输出html就行了,难的是DropDownList和TreeView控件,下面两个方法是返回它们所需的Json数据:

        ///<summary>
        /// 获取树视图Json数据
        ///</summary>
        [Action]
        public void GetTreeViewPermissionJsonData(Guid systemId, Guid permissionItemId, string[] checkedIds)
        {
            PermissionItemModel permissionItem = PermissionItemService.GetById(permissionItemId);

            // 转为对象
            PermissionTreeViewJsonData nodes = PermissionUtils.ParsePermissionControlJsonData<PermissionTreeViewJsonData>(this, systemId, permissionItem);

            // 初始已选数据
            PermissionUtils.InitTreeViewCheckedNodes(nodes, checkedIds);

            JsonResult(nodes);
        }

        ///<summary>
        /// 获取下拉框Json数据
        ///</summary>
        [Action]
        public void GetDropDownListPermissionJsonData(Guid systemId, Guid permissionItemId, string selectedValue)
        {
            PermissionItemModel permissionItem = PermissionItemService.GetById(permissionItemId);

            // 先转为对象
            PermissionDropDownListJsonData options = PermissionUtils.ParsePermissionControlJsonData<PermissionDropDownListJsonData>(this, systemId, permissionItem);

            // 初始已选数据
            PermissionUtils.InitDropDownListSelectedOptions(options, selectedValue);

            JsonResult(options);
        }

 

重点工作都交给了PermissionUtils助手类来处理了,请看下面的代码

public static class PermissionUtils
    public static class PermissionUtils
    {
        ///<summary>
        /// 获取提交的权限
        ///</summary>
        ///<param name="formValues"></param>
        ///<param name="permissionGroupItems"></param>
        ///<returns></returns>
        public static Dictionary<string, PermissionValueModel> GetPostedPermissionValues(NameValueCollection formValues, List<PermissionGroupItemsModel> permissionGroupItems)
        {
            Dictionary<string, PermissionValueModel> permissionValues = new Dictionary<string, PermissionValueModel>(StringComparer.OrdinalIgnoreCase);
            foreach (var groupItem in permissionGroupItems)
            {
                foreach (var item in groupItem.Items)
                {
                    string value = formValues.GetString(item.Code);
                    if (!string.IsNullOrEmpty(value))
                    {
                        if (item.DisplayStyle == PermissionItemDisplayStyle.CheckBox)
                        {
                            value = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)[0];
                        }
                        PermissionValueModel permissionValue = new PermissionValueModel
                        {
                            Code = item.Code,
                            DisplayName = item.DisplayName,
                            DisplayStyle = item.DisplayStyle,
                            Value = value
                        };
                        permissionValues.Add(permissionValue.Code, permissionValue);
                    }
                }
            }

            return permissionValues;
        }

        public static void ServerModelsToPermissionTreeViewNodes(List<PermissionTreeViewNode> nodesToSave, Action<PermissionTreeViewNode> alterNode, IEnumerable<ServerModel> serversToConvert, Guid serverParentId)
        {
            // 过虑并排序
            var sortedServers = serversToConvert.Where(s => s.ParentId == serverParentId).OrderBy(s => s.Order);

            foreach (ServerModel server in sortedServers)
            {
                PermissionTreeViewNode node = new PermissionTreeViewNode(server.Id.ToString(), server.IsGroup, server.Name);

                alterNode(node);

                nodesToSave.Add(node);

                if (server.IsGroup)
                {
                    // 递归,继续初始化孩子节点
                    List<PermissionTreeViewNode> nodes = nodesToSave[nodesToSave.Count - 1].childs;
                    IEnumerable<ServerModel> servers = serversToConvert.Except(sortedServers);
                    ServerModelsToPermissionTreeViewNodes(nodes, alterNode, servers, server.Id);
                }
            }
        }

        #region 权限控件Json数据初始化

        ///<summary>
        /// 
        ///</summary>
        ///<typeparam name="T"></typeparam>
        ///<param name="mode"></param>
        ///<param name="systemId"></param>
        ///<param name="permissionItem"></param>
        ///<returns></returns>
        public static T ParsePermissionControlJsonData<T>(Mode mode, Guid systemId, PermissionItemModel permissionItem)
            where T : class, new()
        {
            string jsonData = permissionItem.JsonDataConst;

            // 如果设置了地址
            string jsonDataUrl = permissionItem.JsonDataUrl.Trim().Replace("\\", "/");
            if (!string.IsNullOrEmpty(jsonDataUrl))
            {
                // 如果是相对地址
                if (jsonDataUrl.IndexOf("://") == -1)
                {
                    // 确保为完整地址
                    jsonDataUrl = mode.Url.Content("~/" + jsonDataUrl.TrimStart('/'), true);
                }
                // 附加参数 systemId、permissionCode
                string tail = string.Empty;
                if (jsonDataUrl.IndexOf('#') > -1)
                {
                    string[] array = jsonDataUrl.Split('#');
                    jsonDataUrl = array[0];
                    tail = array[1];
                }
                if (jsonDataUrl.IndexOf('?') == -1)
                {
                    jsonDataUrl = string.Concat(jsonDataUrl, "?systemId=", systemId, "&permissionCode=", permissionItem.Code);
                }
                else
                {
                    jsonDataUrl = string.Concat(jsonDataUrl.TrimEnd('&'), "&systemId=", systemId, "&permissionCode=", permissionItem.Code);
                }
                if (!string.IsNullOrEmpty(tail))
                {
                    jsonDataUrl = string.Concat(jsonDataUrl, "#", tail);
                }

                // 获取远程Json数据
                jsonData = WebRequestHelper.HttpGet(jsonDataUrl, mode.Request.Url.AbsoluteUri, Encoding.UTF8);
            }

            // 转为对象
            return ObjectSerializer.ConvertFromJsonStringEx<T>(jsonData);
        }

        ///<summary>
        /// 
        ///</summary>
        ///<param name="options"></param>
        ///<param name="selectedValue"></param>
        public static void InitDropDownListSelectedOptions(IEnumerable<PermissionDropDownListOption> options, string selectedValue)
        {
            // 先全不选
            foreach (PermissionDropDownListOption option in options)
            {
                option.selected = false;
            }
            // 初始化已选
            if (selectedValue != null)
            {
                foreach (PermissionDropDownListOption option in options)
                {
                    option.selected = (option.value == selectedValue);
                }
            }
        }

        ///<summary>
        /// 
        ///</summary>
        ///<param name="nodes"></param>
        ///<param name="checkedIds"></param>
        public static void InitTreeViewCheckedNodes(IEnumerable<PermissionTreeViewNode> nodes, string[] checkedIds)
        {
            // 先全不选
            CheckTreeViewNodes(nodes, false);
            if (checkedIds != null && checkedIds.Length > 0)
            {
                // 初始化已选节点
                InitTreeViewCheckedNodesImpl(nodes, checkedIds);
                // 如果父节点全选,要确保以后新增孩子节点时也是要是已选状态的
                MakeSureTreeViewCheckAllNodes(nodes);
            }
        }


        private static void CheckTreeViewNodes(IEnumerable<PermissionTreeViewNode> nodes, bool @checked)
        {
            foreach (var node in nodes)
            {
                node.@checked = @checked;
                // 递归
                CheckTreeViewNodes(node.childs, @checked);
            }
        }
        private static void InitTreeViewCheckedNodesImpl(IEnumerable<PermissionTreeViewNode> nodes, string[] checkedIds)
        {
            if (checkedIds != null)
            {
                foreach (var node in nodes)
                {
                    if (checkedIds.Any(id => id == node.id))
                    {
                        node.@checked = true;
                    }
                    // 递归
                    InitTreeViewCheckedNodesImpl(node.childs, checkedIds);
                }
            }
        }
        private static void MakeSureTreeViewCheckAllNodes(IEnumerable<PermissionTreeViewNode> nodes)
        {
            foreach (var node in nodes)
            {
                // 如果父节点全选,要确保以后新增孩子节点时也是要是已选状态的
                if (node.isParent && node.@checked)
                {
                    CheckTreeViewNodes(node.childs, true);
                }
                // 递归
                MakeSureTreeViewCheckAllNodes(node.childs);
            }
        }

        #endregion
    }

 

显示控件处理完了,那保存权限值呢?获取权限值的实现也放在PermissionUtils助手类里了,第一个方法GetPostedPermissionValues就是获取提交的权限值。

 

三、验权的代码实现

每个用户有多个角色,又有永久和临时权限,那总要处理权限的合理继承吧,本方案是这样处理的:

1. 单选框 与 树视图 类型,在 角色权限、永久权限、临时权限(有效时期内) 中任何已勾选的权限都会一直会继承下去;

2. 文本框 与 下拉框 类型,是按 临时权限 -〉永久权限 -〉角色权限(按排序的顺序) 的顺序,前者的权限为空或没有选择时才会继承后者的权限值;

这些处理都在用户登录成功的时候处理的,并保存权限值到一个字典里,实现代码在MDMS.UserApiModule项目中的UserApiService类:

合并用户权限
        private Dictionary<string, PermissionValueModel> GetUserPermissions(Guid systemId, Guid userId, List<RoleModel> roles)
        {
            Dictionary<string, PermissionValueModel> permissions = new Dictionary<string, PermissionValueModel>(StringComparer.OrdinalIgnoreCase);

            // 先初始化原始权限
            List<PermissionItemModel> rowPermissionItems = DataProviderManager.Get<IPermissionItemProvider>().GetAllBySystemId(systemId);
            foreach (PermissionItemModel item in rowPermissionItems)
            {
                permissions.Add(item.Code, new PermissionValueModel
                {
                    Code = item.Code,
                    DisplayName = item.DisplayName,
                    DisplayStyle = item.DisplayStyle,
                    Value = (item.DisplayStyle == PermissionItemDisplayStyle.CheckBox ? "false" : string.Empty)
                });
            }

            // 个人权限继承说明: 
            // 1. 单选框 与 树视图 类型,在 角色权限、永久权限、临时权限(有效时期) 中任何已勾选的权限都会一直会继承下去; 
            // 2. 文本框 与 下拉框 类型,是按 临时权限 -〉永久权限 -〉角色权限(按排序的顺序) 的顺序,前者的权限为空或没有选择时才会继承后者的权限值;

            // 临时权限
            UserTempPermissionModel userTempPermission = DataProviderManager.Get<IUserTempPermissionProvider>().GetByUserIdAndSystemId(userId, systemId);
            if (userTempPermission.UserId == userId && userTempPermission.SystemId == systemId
                && userTempPermission.Enabled && userTempPermission.BeginDate <= DateTime.Now && DateTime.Now <= userTempPermission.EndDate)
            {
                // 存在且启用且在有效期内时才合并
                UnionPermissions(permissions, userTempPermission.PermissionJsonData);
            }
            // 永久权限
            UserPermissionModel userPermission = DataProviderManager.Get<IUserPermissionProvider>().GetByUserIdAndSystemId(userId, systemId);
            if (userPermission.UserId == userId && userPermission.SystemId == systemId)
            {
                // 存在时才合并
                UnionPermissions(permissions, userPermission.PermissionJsonData);
            }
            // 合并所有角色中的权限
            foreach (RoleModel role in roles)
            {
                UnionPermissions(permissions, role.PermissionJsonData);
            }

            return permissions;
        }

        private void UnionPermissions(Dictionary<string, PermissionValueModel> to, string fromJsonData)
        {
            if (string.IsNullOrEmpty(fromJsonData))
            {
                return; // 没权限需要处理
            }

            Dictionary<string, PermissionValueModel> temp = ObjectSerializer.ConvertFromJsonStringEx<Dictionary<string, PermissionValueModel>>(fromJsonData);

            foreach (KeyValuePair<string, PermissionValueModel> pair in temp)
            {
                PermissionValueModel value;
                if (to.TryGetValue(pair.Key, out value))
                {
                    // 已存在,更新权限值
                    switch (value.DisplayStyle)
                    {
                        case PermissionItemDisplayStyle.CheckBox:
                            // 没有权限就继承
                            if (Utils.StringToBool(value.Value, false) == false)
                            {
                                value.Value = pair.Value.Value;
                            }
                            break;
                        case PermissionItemDisplayStyle.TextBox:
                        case PermissionItemDisplayStyle.DropDownList:
                            // TextBox:如果为空则继承后者
                            // DropDownList:如果没选择则继承后者
                            if (value.Value.IsNullOrTrimedEmpty())
                            {
                                value.Value = pair.Value.Value;
                            }
                            break;
                        case PermissionItemDisplayStyle.TreeView:
                            // 合并不重复的权限
                            string tempString;
                            HashSet<string> toSave = new HashSet<string>();
                            HashSet<string> toUnion = new HashSet<string>();
                            value.Value.Split(',').ForEach(s =>
                            {
                                if ((tempString = s.Trim()) != string.Empty)
                                {
                                    toSave.Add(tempString);
                                }
                            });
                            pair.Value.Value.Split(',').ForEach(s =>
                            {
                                if ((tempString = s.Trim()) != string.Empty)
                                {
                                    toSave.Add(tempString);
                                }
                            });
                            // save the result unioned
                            value.Value = string.Join(",", toSave.Union(toUnion).ToArray());
                            break;
                        default:
                            throw new Exception("Unknown PermissionItemDisplayStyle.");
                    }
                    // 保存权限值
                    to[pair.Key] = value;
                }
                else
                {
                    // 不存在,添加新权限值
                    to.Add(pair.Key, pair.Value);
                }
            }
        }

 

要验证权限,那首先要做的就是获取权限值,在MDMS.UserApiModule项目中的ServiceContextBase类中实现所有类型的权限值获取方法,所以子系统只要继承这个类,就可以轻松的进行权限的验证了,请看获取权限值的方法实现:

Permission Services
        #region Permission Services

        private ReadFreeCache<string, object> PermissionValueCache
        {
            get
            {
                if (User.Profile.Id == Guid.Empty)
                {
                    throw new Exception("No logined user.");
                }

                HttpContext context = HttpContext.Current;
                if (context == null)
                {
                    // 非 Web 系统
                    return permissionValueCache;
                }
                else
                {
                    ReadFreeCache<string, object> cache = context.Session["___PermissionValueCache"] as ReadFreeCache<string, object>;
                    if (cache == null)
                    {
                        cache = ReadFreeCache<string, object>.Create(StringComparer.OrdinalIgnoreCase);
                        context.Session["___PermissionValueCache"] = cache;
                    }

                    return cache;
                }
            }
        }

        ///<summary>
        /// 
        ///</summary>
        ///<param name="permissionCode"></param>
        ///<returns></returns>
        public PermissionValueModel GetPermissionValue(string permissionCode)
        {
            permissionCode.ThrowsIfNullOrEmpty("permissionCode");

            PermissionValueModel permission;
            if (User.Permissions.TryGetValue(permissionCode, out permission))
            {
                return permission;
            }

            throw new Exception("PermissionCode \"" + permissionCode + "\" does not exist.");
        }

        ///<summary>
        /// 
        ///</summary>
        ///<param name="permissionCode"></param>
        ///<returns></returns>
        public bool GetCheckBoxPermissionValue(string permissionCode)
        {
            permissionCode.ThrowsIfNullOrEmpty("permissionCode");

            PermissionValueModel permission = GetPermissionValue(permissionCode);

            if (permission.DisplayStyle != PermissionItemDisplayStyle.CheckBox)
            {
                throw new Exception("DisplayStyle of permission code \"" + permissionCode + "\" is not CheckBox.");
            }

            return Utils.StringToBool(permission.Value, false);
        }

        ///<summary>
        /// 
        ///</summary>
        ///<typeparam name="T"></typeparam>
        ///<param name="permissionCode"></param>
        ///<returns></returns>
        public T GetTextBoxPermissionValue<T>(string permissionCode)
        {
            return GetTextBoxPermissionValue(permissionCode, default(T));
        }

        ///<summary>
        /// 
        ///</summary>
        ///<typeparam name="T"></typeparam>
        ///<param name="permissionCode"></param>
        ///<param name="defaultValue"></param>
        ///<returns></returns>
        public T GetTextBoxPermissionValue<T>(string permissionCode, T defaultValue)
        {
            permissionCode.ThrowsIfNullOrEmpty("permissionCode");

            string permissionCodeKey = string.Format("{0}_{1}", User.Profile.UserName, permissionCode);

            // TextBox权限使用缓存,不必每次处理数据转换
            object permissionValue = PermissionValueCache.Get(permissionCodeKey, key =>
            {
                PermissionValueModel permission = GetPermissionValue(permissionCode);

                if (permission.DisplayStyle != PermissionItemDisplayStyle.TextBox)
                {
                    throw new Exception("DisplayStyle of permission code \"" + permissionCode + "\" is not TextBox.");
                }

                return Utils.StringTo<T>(permission.Value, defaultValue);
            });

            return (T)permissionValue;
        }

        ///<summary>
        /// 
        ///</summary>
        ///<typeparam name="T"></typeparam>
        ///<param name="permissionCode"></param>
        ///<returns></returns>
        public T GetDropDownListPermissionValue<T>(string permissionCode)
        {
            return GetDropDownListPermissionValue(permissionCode, default(T));
        }

        ///<summary>
        /// 
        ///</summary>
        ///<typeparam name="T"></typeparam>
        ///<param name="permissionCode"></param>
        ///<param name="defaultValue"></param>
        ///<returns></returns>
        public T GetDropDownListPermissionValue<T>(string permissionCode, T defaultValue)
        {
            permissionCode.ThrowsIfNullOrEmpty("permissionCode");

            string permissionCodeKey = string.Format("{0}_{1}", User.Profile.UserName, permissionCode);

            // DropDownList权限使用缓存,不必每次处理数据转换
            object permissionValue = PermissionValueCache.Get(permissionCodeKey, key =>
            {
                PermissionValueModel permission = GetPermissionValue(permissionCode);

                if (permission.DisplayStyle != PermissionItemDisplayStyle.DropDownList)
                {
                    throw new Exception("DisplayStyle of permission code \"" + permissionCode + "\" is not DropDownList.");
                }

                return Utils.StringTo<T>(permission.Value, defaultValue);
            });

            return (T)permissionValue;
        }

        ///<summary>
        /// 
        ///</summary>
        ///<typeparam name="T"></typeparam>
        ///<param name="permissionCode"></param>
        ///<returns></returns>
        public List<T> GetTreeViewPermissionValue<T>(string permissionCode)
        {
            return GetTreeViewPermissionValue(permissionCode, (Func<List<T>, List<T>>)null);
        }

        ///<summary>
        /// 
        ///</summary>
        ///<typeparam name="T"></typeparam>
        ///<param name="permissionCode"></param>
        ///<param name="rectifyValues">为防止父节点被选后,后来新增的子节点没有被加进来,请根据具体情况修正权限值列表</param>
        ///<returns></returns>
        public List<T> GetTreeViewPermissionValue<T>(string permissionCode, Func<List<T>, List<T>> rectifyValues)
        {
            permissionCode.ThrowsIfNullOrEmpty("permissionCode");

            string permissionCodeKey = string.Format("{0}_{1}_{2}",
                User.Profile.UserName,
                permissionCode,
                (rectifyValues == null ? string.Empty : "rectifyValues"));

            // TreeView权限使用缓存,不必每次处理数据转换
            object permissionValue = PermissionValueCache.Get(permissionCodeKey, key =>
            {
                PermissionValueModel permission = GetPermissionValue(permissionCode);

                if (permission.DisplayStyle != PermissionItemDisplayStyle.TreeView)
                {
                    throw new Exception("DisplayStyle of permission code \"" + permissionCode + "\" is not TreeView.");
                }

                List<T> values = null;
                if (string.IsNullOrEmpty(permission.Value))
                {
                    values = new List<T>();
                }
                else
                {
                    List<T> tempValues = new List<T>();
                    foreach (string value in permission.Value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
                    {
                        tempValues.Add(Utils.StringTo<T>(value));
                    }

                    if (rectifyValues == null)
                    {
                        rectifyValues = v => v;
                    }
                    values = rectifyValues(tempValues);
                }

                return values;
            });

            return (List<T>)permissionValue;
        }

        #endregion

另外值得说的是,GetTreeViewPermissionValue方法有个Func<List<T>, List<T>> rectifyValues参数,它的作用是,如果在授权时勾选了某个根节点,那表示此根节点下的所有权限都是有的,包括以后在该根节点新加的子节点,所以需要额外根据根节点获取所有的子节点,以确保获取的权限是完整的。

在主数据系统设计中,主数据系统也被当成自己的一个子系统来处理了,下面看看主数据页面基类是怎么获取权限的?

验证权限
        #region 验证权限

        ///<summary>
        /// 选择框权限是否无效
        ///</summary>
        ///<param name="permissionCode"></param>
        ///<returns></returns>
        protected bool IsCheckBoxPermissionInvalid(string permissionCode)
        {
            return (ServiceContext.Current.GetCheckBoxPermissionValue(permissionCode) == false);
        }

        ///<summary>
        /// 树视图权限是否无效
        ///</summary>
        ///<param name="permissionCode"></param>
        ///<param name="ids">需要验证的自定义数据</param>
        ///<returns></returns>
        protected bool IsTreeViewPermissionInvalid(string permissionCode, params Guid[] ids)
        {
            permissionCode.ThrowsIfNullOrEmpty("permissionCode");

            if (ids == null || ids.Length == 0 || ids[0] == Guid.Empty/* id为空时不用检验 */)
            {
                return false;
            }

            // 获取权限值
            List<Guid> scopeList = ServiceContext.Current.GetTreeViewPermissionValue<Guid>(permissionCode, list =>
            {
                List<Guid> retList = list;

                // 如果有已选数据,根据情况进行数据矫正
                if (list.Count > 0)
                {
                    switch (permissionCode.ToLower())
                    {
                        case "manage_role_scope":
                            if (list.Exists(id => id == Guid.Empty))
                            {
                                // 全选情况:返回所有ID,包括后来新增的数据
                                retList = (from p in SystemService.GetAll() select p.Id).ToList();
                            }
                            break;
                        case "manage_permission_scope":
                            if (list.Exists(id => id == Guid.Empty))
                            {
                                // 全选情况:返回所有ID,包括后来新增的数据
                                retList = (from p in SystemService.GetAll() select p.Id).ToList();
                            }
                            break;
                        default:
                            throw new Exception("Unknown permissionCode: " + permissionCode);
                    }
                }

                return retList;
            });

            // 验证权限
            bool isInvalid = false;
            if (scopeList.Count == 0)
            {
                // 没有选中数据
                isInvalid = true;
            }
            else
            {
                // 是否有不在范围的?
                foreach (Guid id in ids)
                {
                    if (scopeList.Exists(i => i == id) == false)
                    {
                        // 没有权限,不再继续判断
                        isInvalid = true;
                        break;
                    }
                }
            }

            return isInvalid;
        }

        #endregion

 

有了上面的页面基类,最后的权限验证就变得简洁方便了


 

写到这就算结束了,设计中的内容比较多,不好处处仔细的解说。本方案中,用json来保存权限使实现变得简单了很多,而且是采用key/value的字典格式,所以子系统在以后需要新增新的权限项或删除权限项,都不会影响到用户的权限(意思是不用解决权限版本问题,随意添加删除权限都可以正常动作),时间问题只能以这种方式来讲解了,需要深入了解本方案设计的朋友请下载整个系统的源码来看,如果本文对你有帮助,请点击推荐以示支持,谢谢。

 

在线demo: http://mdms.kudystudio.com/

用户/密码:test1/test1 test2/test2 (注:同一用户在另一浏览器登录,另一用户在session失效后会被逼下线)

本文转载目的用于以后学习查看使用。 

原文来自:http://www.cnblogs.com/kudy/archive/2011/11/10/2243810.html

作者: Kudy
出处: http://kudy.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值