百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

《若依ruoyi》第三十八章Ruoyi-数据权限使用拆解

toyiye 2024-06-21 12:28 9 浏览 0 评论

在实际应用中,公司会有多个部门存在,每个部门的职能不一样,看到的数据不一样,每个部门也会分层级,例如普通员工职能看到自己创建的数据,部门领导可以看到该部门下的所有员工数据,系统需要实现这一逻辑,就是数据权限功能

1、功能实现操作界面

第一步:点击右侧菜单导航栏,点击角色管理


第二步:点击角色右侧的更多的数据权限


数据权限分为:全部数据、自定义数据、本部门数据、本部门以及一下数据、仅本人数据权限。

2、数据权限配置

1、如下是弹窗显示数据权限代码

<!-- 分配角色数据权限对话框 -->
<el-dialog :title="title" :visible.sync="openDataScope" width="500px" append-to-body>
  <el-form :model="form" label-width="80px">
    <el-form-item label="角色名称">
      <el-input v-model="form.roleName" :disabled="true" />
    </el-form-item>
    <el-form-item label="权限字符">
      <el-input v-model="form.roleKey" :disabled="true" />
    </el-form-item>
    <el-form-item label="权限范围">
      <el-select v-model="form.dataScope" @change="dataScopeSelectChange">
        <el-option
          v-for="item in dataScopeOptions"
          :key="item.value"
          :label="item.label"
          :value="item.value"
        ></el-option>
      </el-select>
    </el-form-item>
    <el-form-item label="数据权限" v-show="form.dataScope == 2">
      <el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
      <el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>
      <el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox>
      <el-tree
        class="tree-border"
        :data="deptOptions"
        show-checkbox
        default-expand-all
        ref="dept"
        node-key="id"
        :check-strictly="!form.deptCheckStrictly"
        empty-text="加载中,请稍候"
        :props="defaultProps"
      ></el-tree>
    </el-form-item>
  </el-form>
  <div slot="footer" class="dialog-footer">
    <el-button type="primary" @click="submitDataScope">确 定</el-button>
    <el-button @click="cancelDataScope">取 消</el-button>
  </div>
</el-dialog>

2、下面是提交数据权限代码

/** 提交按钮(数据权限) */
submitDataScope: function() {
  if (this.form.roleId != undefined) {
    this.form.deptIds = this.getDeptAllCheckedKeys();
    dataScope(this.form).then(response => {
      this.$modal.msgSuccess("修改成功");
      this.openDataScope = false;
      this.getList();
    });
  }
},

3、后台api接口处理修改数据权限

1、如下是接口代码

/**
 * 修改保存数据权限
 */
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.UPDATE)
@PutMapping("/dataScope")
public AjaxResult dataScope(@RequestBody SysRole role)
{
    roleService.checkRoleAllowed(role);
    roleService.checkRoleDataScope(role.getRoleId());
    return toAjax(roleService.authDataScope(role));
}

业务逻辑说明:

1)、检查角色是否允许操作,针对登录者操作,具体代码roleService.checkRoleAllowed(role);

2)、校验角色是否有数据权限,roleService.checkRoleDataScope(role.getRoleId());

3)、修改数据权限信息,就是将角色绑定到角色部门表,并保存数据权限

如下是角色数据库表:

CREATE TABLE `sys_role` (
  `role_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '角色ID',
  `role_name` varchar(30) NOT NULL COMMENT '角色名称',
  `role_key` varchar(100) NOT NULL COMMENT '角色权限字符串',
  `role_sort` int(4) NOT NULL COMMENT '显示顺序',
  `data_scope` char(1) DEFAULT '1' COMMENT '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)',
  `menu_check_strictly` tinyint(1) DEFAULT '1' COMMENT '菜单树选择项是否关联显示',
  `dept_check_strictly` tinyint(1) DEFAULT '1' COMMENT '部门树选择项是否关联显示',
  `status` char(1) NOT NULL COMMENT '角色状态(0正常 1停用)',
  `del_flag` char(1) DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)',
  `create_by` varchar(64) DEFAULT '' COMMENT '创建者',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_by` varchar(64) DEFAULT '' COMMENT '更新者',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `remark` varchar(500) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`role_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='角色信息表';

data_scope:数据范围。

4、具体数据权限实现方式

在执行mysql到时候,通过spring 的aop切面,在执行sql前,追加数据过滤的sql语句。

具体代码如下

代码路径是在ruoyi-framewro模块下的

package com.ruoyi.framework.aspectj;
DataScopeAspect

/**
 * 数据范围过滤
 *
 * @param joinPoint 切点
 * @param user 用户
 * @param deptAlias 部门别名
 * @param userAlias 用户别名
 * @param permission 权限字符
 */
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, String permission)
{
    StringBuilder sqlString = new StringBuilder();
    List<String> conditions = new ArrayList<String>();

    for (SysRole role : user.getRoles())
    {
        String dataScope = role.getDataScope();
        if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope))
        {
            continue;
        }
        if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions())
                && !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
        {
            continue;
        }
        if (DATA_SCOPE_ALL.equals(dataScope))
        {
            sqlString = new StringBuilder();
            conditions.add(dataScope);
            break;
        }
        else if (DATA_SCOPE_CUSTOM.equals(dataScope))
        {
            sqlString.append(StringUtils.format(
                    " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
                    role.getRoleId()));
        }
        else if (DATA_SCOPE_DEPT.equals(dataScope))
        {
            sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
        }
        else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
        {
            sqlString.append(StringUtils.format(
                    " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
                    deptAlias, user.getDeptId(), user.getDeptId()));
        }
        else if (DATA_SCOPE_SELF.equals(dataScope))
        {
            if (StringUtils.isNotBlank(userAlias))
            {
                sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
            }
            else
            {
                // 数据权限为仅本人且没有userAlias别名不查询任何数据
                sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
            }
        }
        conditions.add(dataScope);
    }

    // 多角色情况下,所有角色都不包含传递过来的权限字符,这个时候sqlString也会为空,所以要限制一下,不查询任何数据
    if (StringUtils.isEmpty(conditions))
    {
        sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
    }

    if (StringUtils.isNotBlank(sqlString.toString()))
    {
        Object params = joinPoint.getArgs()[0];
        if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
        {
            BaseEntity baseEntity = (BaseEntity) params;
            baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
        }
    }
}

如上述代码,根据数据库配置的data_scope字段,决定增加哪些sql语句。

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码