深度解析RBAC用户-角色-权限设计方案,以及核心逻辑代码的讲解

Posted Roninaxious

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深度解析RBAC用户-角色-权限设计方案,以及核心逻辑代码的讲解相关的知识,希望对你有一定的参考价值。

首先对于b2b、b2c等这一些网站后台,一般情况下都需要权限管理的设计与实现,对于这部分,通常是固定不变的,每次只需要做少量的改动即可。

如何设计这几张表呢?

RBAC(基于角色的访问控制),也就是用户通过角色与权限进行关联;一个角色拥有多个角色,一个角色拥有多个权限;这样就构成了下图中的用户-角色-权限的授权模型;

用户与角色之间、角色与权限之间一般是多对多的关系。对于一对多关系表的设计中,我们一般是多的那一方多加入一个字段即可;而对于多对多关系表的设计,一般来说我们要借助第三方表


这五张表是至少的,也就是说权限的设计要>=5张表,具体需要多少张表还需要根据系统业务做相应的增加。

从上图中我们可以观察出,权限表与角色表通过role_permission表联系起来,在role_permission表中必要的两个字段就是权限id和角色id;当然用户表和角色表也一样。

有关核心的逻辑代码

由于一个后台系统可能包含多级菜单(权限),比如电器商品是一级菜单,电器商品删除是二级菜单等等,所以在对所有的菜单(权限)进行查询的过程中,需要进行树状显示。所以需要进行递归遍历。

	@Override
    public List<Permission> queryAllMenu() {
        //1 查询菜单表所有数据
        QueryWrapper<Permission> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("id");
        List<Permission> permissionList = baseMapper.selectList(wrapper);
        //2 把查询所有菜单list集合按照要求进行封装
        List<Permission> resultList = bulidPermission(permissionList);
        return resultList;
    }

    //把返回所有菜单list集合进行封装的方法
    public static List<Permission> bulidPermission(List<Permission> permissionList) {

        //创建list集合,用于数据最终封装
        List<Permission> finalNode = new ArrayList<>();
        //把所有菜单list集合遍历,得到顶层菜单 pid=0菜单,设置level是1
        for(Permission permissionNode : permissionList) {
            //得到顶层菜单 pid=0菜单
            if("0".equals(permissionNode.getPid())) {
                //设置顶层菜单的level是1
                permissionNode.setLevel(1);
                //根据顶层菜单,向里面进行查询子菜单,封装到finalNode里面
                finalNode.add(selectChildren(permissionNode,permissionList));
            }
        }
        return finalNode;
    }

    private static Permission selectChildren(Permission permissionNode, List<Permission> permissionList) {
        //1 因为向一层菜单里面放二层菜单,二层里面还要放三层,把对象初始化
        permissionNode.setChildren(new ArrayList<Permission>());

        //2 遍历所有菜单list集合,进行判断比较,比较id和pid值是否相同
        for(Permission it : permissionList) {
            //判断 id和pid值是否相同
            if(permissionNode.getId().equals(it.getPid())) {
                //把父菜单的level值+1
                int level = permissionNode.getLevel()+1;
                it.setLevel(level);
                //如果children为空,进行初始化操作
                if(permissionNode.getChildren() == null) {
                    permissionNode.setChildren(new ArrayList<Permission>());
                }
                //把查询出来的子菜单放到父菜单里面
                permissionNode.getChildren().add(selectChildren(it,permissionList));
            }
        }
        return permissionNode;
    }

下面是递归删除权限的逻辑,思路是递归查询该id下的所有子权限,然后批量删除即可。

    @Override
    public void removeChildById(String id) {
        List<String> idList = new ArrayList<>();
        selectPermissionIdList(idList, id);
        idList.add(id);
        baseMapper.deleteBatchIds(idList);
    }

    private void selectPermissionIdList(List<String> idList, String id) {
        QueryWrapper<Permission> wrapper = new QueryWrapper<>();
        wrapper.eq("pid", id).select("id");
        List<Permission> permissionList = baseMapper.selectList(wrapper);
        permissionList.stream().forEach(permission -> {
            idList.add(permission.getId());
            this.selectPermissionIdList(idList, permission.getId());
        });
    }

以上是关于深度解析RBAC用户-角色-权限设计方案,以及核心逻辑代码的讲解的主要内容,如果未能解决你的问题,请参考以下文章

RBAC用户角色权限设计方案

进阶RBAC用户角色权限设计方案

RBAC用户角色权限设计方案转载

用户 角色 权限 设计方案(扩展RBAC)

扩展RBAC用户角色权限设计方案

ToB产品权限系统设计(一RBAC模型)