在实际应用中,公司会有多个部门存在,每个部门的职能不一样,看到的数据不一样,每个部门也会分层级,例如普通员工职能看到自己创建的数据,部门领导可以看到该部门下的所有员工数据,系统需要实现这一逻辑,就是数据权限功能
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语句。
来源:
互联网
本文观点不代表源码解析立场,不承担法律责任,文章及观点也不构成任何投资意见。
评论列表