其他笔记:应用程序权限设计

基于角色的权限设计
这种方案是最常见也是比较简单的方案,不过通常有这种设计已经够了,这种方案对于每一个操作不做控制,只是在程序中根据角色对是否具有操作的权限进行控制
在这里插入图片描述

基于操作的权限设计
这种模式下每一个操作都在数据库中有记录,用户是否拥有该操作的权限也在数据库中有记录,结构如下:
在这里插入图片描述

基于角色和操作的权限设计
在这里插入图片描述
如上图所示,我们在添加了Role,和RoleAction表,这样子就可以减少UserAction中的记录,并且使设计更灵活一点。

但是这种方案在用户需求的考验之下也可能显得不够灵活够用,例如当用户要求临时给某位普通员工某操作权限时,我们就需要新增加一种新的用户角色,但是这种用户角色是不必要的,因为它只是一种临时的角色,如果添加一种角色还需要在收回此普通员工权限时删除此角色,我们需要设计一种更合适的结构来满足用户对权限设置的要求。

组合的权限设计
在这里插入图片描述
我们可以看到在上图中添加了UserAction表,使用此表来添加特殊用户的权限,改表中有一个字段HasPermission可以决定用户是否有某种操作的权限,改表中记录的权限的优先级要高于UserRole中记录的用户权限。这样在应用程序中我们就需要通过UserRole和UserAction两张表中的记录判断权限。

有可能用户还会给出这样的需求:对于某一种action所操作的对象某一些记录会有权限,而对于其他的记录没有权限,比如说一个内容管理系统,对于某一些频道某个用户有修改的权限,而对于另外一些频道没有修改的权限,这时候我们需要设计更复杂的权限机制。

对于同一种实体(资源)用户可以对一部分记录有权限,而对于另外一些记录没有权限的权限设计
在这里插入图片描述

对于这样的需求我们就需要对每一种不同的资源创建一张权限表,在上图中对Content和Channel两种资源分别创建了UserActionContent和UserActionChannel表用来定义用户对某条记录是否有权限;这种设计是可以满足用户需求的但是不是很经济,UserActionChannel和UserActionContent中的记录会很多,而在实际的应用中并非需要记录所有的记录的权限信息,有时候可能只是一种规则,比如说对于根Channel什么级别的人有权限;这时候呢我们就可以定义些规则来判断用户权限,下面就是这种设计。

涉及资源,权限和规则的权限设计
在这里插入图片描述

        #region 过滤登录用户的菜单权限
        /// <summary>
        /// 1: 可以按照用户---角色---权限这条线找出登录用户的权限,放在一个集合中。
        /// 2:可以按照用户---权限这条线找出用户的权限,放在一个集合中。
        /// 3:将这两个集合合并成一个集合。
        /// 4:把禁止的权限从总的集合中清除。
        /// 5:将总的集合中的重复权限清除。
        /// 6:把过滤好的菜单权限生成JSON返回。
        /// </summary>
        /// <returns></returns>
        public ActionResult Getmenus()
        {
            //1: 可以按照用户---角色---权限这条线找出登录用户的权限,放在一个集合中。
            //获取登录用户的信息
            var userInfo = UserInfoService.Load(u => u.Id == LoginUser.Id).FirstOrDefault();
            //获取登录用户的角色.
            var userRoleInfo = userInfo.RoleInfo;
            //根据登录用户的角色获取对应的菜单权限。
            short actionTypeEnum = (short)ActionTypeEnum.MenumActionType;
            var loginUserMenuActions = (from r in userRoleInfo
                                        from a in r.ActionInfo
                                        where a.ActionTypeEnum == actionTypeEnum
                                        select a).ToList();

            //下面语句是错误的,allUserActions是一个大集合该集合中包含了很多小的集合,所以变量b为集合类型
            //var allUserActions = from r in userRoleInfo
            //                     select r.ActionInfo;
            //var mm = from b in allUserActions
            //         where b.ActionTypeEnum == actionTypeEnum
            //         select b;


            // 2:可以按照用户---权限这条线找出用户的权限,放在一个集合中。
            var userActions = from a in userInfo.R_UserInfo_ActionInfo
                              select a.ActionInfo;

            var userMenuActions = (from a in userActions
                                   where a.ActionTypeEnum == actionTypeEnum
                                   select a).ToList();

            // a.ActionInfo不是一个集合,注意理解权限表与用户权限关系表之间的对应关系
            //var userMenuActionse = from a in userInfo.R_UserInfo_ActionInfo
            //                       from b in a.ActionInfo
            //                       where b.ActionTypeEnum == actionTypeEnum
            //                       select b;



            //3:将这两个集合合并成一个集合。
            loginUserMenuActions.AddRange(userMenuActions);

            //4:把禁止的权限从总的集合中清除。
            var forbidActions = (from a in userInfo.R_UserInfo_ActionInfo
                                 where a.IsPass == false
                                 select a.ActionInfoID).ToList();
            var loginUserAllowActions = loginUserMenuActions.Where(a => !forbidActions.Contains(a.Id));

            //5:将总的集合中的重复权限清除。
            var lastLoginUserActions = loginUserAllowActions.Distinct(new EqualityComparer());
            //6:把过滤好的菜单权限生成JSON返回。
            var temp = from a in lastLoginUserActions
                       select new { icon = a.MenuIcon, title = a.ActionInfoName, url = a.Url };
            return Json(temp, JsonRequestBehavior.AllowGet);
        }
        #endregion

猜你喜欢

转载自blog.csdn.net/qq_39827640/article/details/106934437