简单的权限管理系统——数据库设计和实现

一、首先我们需要有三张基础表

1.用户表(Account):包含用户id、登录名、密码、手机号、邮箱、创建时间、账户状态(停用或启用)、备注。

2.角色表(Roles):不同的角色代表了不同的权限, 字段:角色id、角色名、角色信息(不是必要)、角色状态(停用或启用)、备注。

 3.菜单表(Menus):不同的菜单进入的页面具有不同的功能,字段:菜单id、菜单名称、跳转url、是否菜单(因为有些地方可能会把添加模块作为一个单独的页面,而又不希望其直接出现在系统的侧边栏里面,当然我一般使用弹框做添加数据)、菜单icon图标(不必要)、备注、二级菜单id。

 二.有了三张基础表后,我们需要思考三张表之间有怎样的关系。

用户——角色——菜单:

1、用户面对角色:一个用户可以有多个角色,一个角色也可以有多个用户,但一般我们只分配一个角色。所以也可以在用户表中再加一个角色id,不过我这里设计的是一个用户可以有多个角色的情况,所以是多对多的。

那么就需要有一个用户角色关联表(AccountRoles):关联id、用户id、角色id

2、角色面对菜单:一个角色可以有多个菜单,一个菜单也可以被多个角色拥有。所以也是多对多的关系。

那么就要有角色菜单关联表(RoleMenus):关联id、角色id、菜单id

到这里数据库的设计就完成了。

总体的关系图就是这样的

三、模拟一个场景

        在登录成功之后,我们可以根据用户的id去查询它对应的角色,再查出角色对应的菜单,然后在页面渲染菜单集合。就实现了不同用户进入系统得到的是不同的菜单。

        首先用户不直接面对菜单,而是面对角色,而角色拥有菜单,这样用户就间接的拥有了菜单。并且如果我们想给用户新增一个菜单时,只需要给对应的角色多分配一个菜单就可以了。同时如果用户在地址栏强行改url跳转时,也可以通过过滤器对其进行验证,判断是否拥有此菜单。

四、一级菜单和二级菜单的实现

然后重点说一下一级菜单和二级菜单怎么区分,以及怎么把二级菜单归属到一级菜单中:

首先我们知道,一级菜单是直接显示在侧边栏的,而二级则在一级菜单的下面,如:

 那么如果数据库中只有二级菜单,而这些二级菜单都没有所属的一级菜单,是无法显示出来的。但一级菜单下面却可以不需要一定有二级菜单。

回过来看数据库,我们最后有一个pid,用来判断是否是一级还是二级,拟定0为一级,那么不为0的都为二级,那如何判断二级是属于哪个一级下面的呢,这时我们可以把二级的pid设定为一级菜单的MenuID,如图,账户管理、角色管理、菜单管理的pid都是10,而10是一级菜单权限管理的MenuID。

然后可以看我的数据

用户表

 用户有一个角色,这个角色是超级管理员

 

 这个角色对应的菜单

我们需要渲染在页面上的时候可以封装一个类

public class ResultMenu
    {
        public string MenuName { get; set; }
        public string MenuUrl { get; set; }
        public string MenuRemark { get; set; }
        public List<ResultMenu> SubMenu { get; set; }

    }

递归获取菜单

protected List<ResultMenu> GetMenu(List<Menu> menus)
        {
            List<ResultMenu> resultMenus = new List<ResultMenu>();
            // 顶级菜单
            var pMenus = menus.Where(x => x.Pid == 0).ToList();
            foreach (var itemMenu in pMenus)
            {
                ResultMenu resultMenu = new ResultMenu
                {
                    MenuName = itemMenu.Name,
                    MenuRemark = itemMenu.Remark,
                    MenuUrl = itemMenu.Url,
                    SubMenu = GetChildrenMenu(itemMenu.MenuId, menus)
                };

                resultMenus.Add(resultMenu);
            }
            return resultMenus;
        }
        /// <summary>
        /// 获取子菜单
        /// </summary>
        /// <param name="mid">菜单id</param>
        /// <param name="menus">角色拥有的所有菜单</param>
        /// <returns></returns>
        protected List<ResultMenu> GetChildrenMenu(int mid,List<Menu> menus)
        {
            List<ResultMenu> resultMenus = new List<ResultMenu>();
            // 获取子菜单
            var childrenMenus = menus.Where(x => x.Pid == mid).ToList();
            foreach (var itemMenu in childrenMenus)
            {
                ResultMenu resultMenu = new ResultMenu
                {
                    MenuName = itemMenu.Name,
                    MenuRemark = itemMenu.Remark,
                    MenuUrl = itemMenu.Url,
                    SubMenu = GetChildrenMenu(itemMenu.MenuId, menus)
                };
                resultMenus.Add(resultMenu);
            }

            return resultMenus;
        }

最后得到这样的数据格式

需要源码的可以加.net core学习交流群:831181779,在群里@群主即可

  • 41
    点赞
  • 118
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不想只会CRUD的猿某人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值