若依框架|基于若依框架的数据权限。

数据权限 数据权限和菜单权限不一样

菜单权限:
根据不同的性质的用户,显示不同的菜单。
数据权限:
设置权限,不同的用户只能访问本用户的数据,或者本部门的数据。当然对于特殊的领导可以跨部门访问数据。这些都是可以设置权限。
此代码的数据权限是基于若依框架,基于部门权限的简单数据权限设置。

实现功能 【若依框架|基于若依框架的数据权限。】本系统针对多个幼儿园,不同的幼儿园园长,只能增删查改属于本幼儿园的儿童信息。但是所有的儿童信息都储存在同一个表中。此时就需要对不同的幼儿园园长设置数据权限。


实现步骤
  1. 在设置儿童信息表时,添加一个字段部门id(dept_id bigint 20) ,这将作为数据过滤的条件。
若依框架|基于若依框架的数据权限。
文章图片



  1. 在MyBaits中的Mapper文件中的select语句中添加(数据过滤范围)
id="selectKinChildrenInfoVo"> select U.CHILDREN_ID, U.CHILDREN_NAME, U.SEX, BIRTHDAY, U.REGION_CODE, U.HOME_ADDRESS, U.NATION_ID, U.PARENT_NAME, U.PARENT_PHONE ,U.dept_id from kin_children_info U id="selectKinChildrenInfoList" parameterType="KinChildrenInfo" resultMap="KinChildrenInfoResult"> ${params.dataScope} and CHILDREN_NAME like concat('%', #{childrenName}, '%') and SEX = #{SEX} and BIRTHDAY = #{BIRTHDAY} and REGION_CODE = #{regionCode} and HOME_ADDRESS = #{homeAddress} and NATION_ID = #{nationId} and PARENT_NAME like concat('%', #{parentName}, '%') and PARENT_PHONE = #{parentPhone}


  1. 在service层添加注解 (@DataScope)
/** * 查询儿童信息列表 * U是儿童信息表的别名 * @param kinChildrenInfo 儿童信息 * @return 儿童信息 * */ @Override @DataScope(deptAlias = "U") public List selectKinChildrenInfoList(KinChildrenInfo kinChildrenInfo) { return kinChildrenInfoMapper.selectKinChildrenInfoList(kinChildrenInfo); }


解释 上述了过后已经实现了我需要的,基于部门的数据权限访问。
当然,这不能帮助我们弄清楚,具体的实现机制。

解释注解 @DataScope(deptAlias=“U”) 这就需要我们去看若依框架中DataScopeAspect.java这个类(用来进行数据过滤处理的 基于切面编程)
package com.ruoyi.framework.aspectj; import java.lang.reflect.Method; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import com.ruoyi.common.annotation.DataScope; import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.framework.util.ShiroUtils; import com.ruoyi.system.domain.SysRole; import com.ruoyi.system.domain.SysUser; /** * 数据过滤处理 * * @author ruoyi */ @Aspect @Component public class DataScopeAspect { /** * 全部数据权限 */ public static final String DATA_SCOPE_ALL = "1"; /** * 自定数据权限 */ public static final String DATA_SCOPE_CUSTOM = "2"; /** * 部门数据权限 */ public static final String DATA_SCOPE_DEPT = "3"; /** * 部门及以下数据权限 */ public static final String DATA_SCOPE_DEPT_AND_CHILD = "4"; /** * 仅本人数据权限 */ public static final String DATA_SCOPE_SELF = "5"; /** * 数据权限过滤关键字 */ public static final String DATA_SCOPE = "dataScope"; // 配置织入点 @Pointcut("@annotation(com.ruoyi.common.annotation.DataScope)") public void dataScopePointCut() { }@Before("dataScopePointCut()") public void doBefore(JoinPoint point) throws Throwable { handleDataScope(point); }protected void handleDataScope(final JoinPoint joinPoint) { // 获得注解 DataScope controllerDataScope = getAnnotationLog(joinPoint); if (controllerDataScope == null) { return; } // 获取当前的用户 SysUser currentUser = ShiroUtils.getSysUser(); if (currentUser != null) { // 如果是超级管理员,则不过滤数据 if (!currentUser.isAdmin()) { dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), controllerDataScope.userAlias()); } } }/** * 数据范围过滤 * * @param joinPoint 切点 * @param user 用户 * @param deptAlias 部门别名 * @param userAlias 用户别名 */ public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias) { StringBuilder sqlString = new StringBuilder(); for (SysRole role : user.getRoles()) { String dataScope = role.getDataScope(); //判断数据权限是否为全部数据 if (DATA_SCOPE_ALL.equals(dataScope)) { sqlString = new StringBuilder(); break; } //判断数据权限是否为自定数据权限 else if (DATA_SCOPE_CUSTOM.equals(dataScope)) { sqlString.append(StringUtils.format( " AND ({}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} )) ", deptAlias, role.getRoleId())); } //判断数据权限是否为部门权限,我所需要的 else if (DATA_SCOPE_DEPT.equals(dataScope)) { //将DataScope注解里表别名,用户的部门id代替占位符 编程字符串 sqlString.append(StringUtils.format(" WHERE {}.dept_id = {} ", deptAlias, user.getDeptId())); } else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) { sqlString.append(StringUtils.format( " AND ({}.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(" AND ({}.user_id = {} )", userAlias, user.getUserId())); } else { // 数据权限为仅本人且没有userAlias别名不查询任何数据 sqlString.append(" AND (1=0) "); } } }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) + ")"); //将刚才添加的语句添加到关键字dataScope,从第一位开始 //用于MyBaits文件中${params.dataScope}附加SQL语句 baseEntity.getParams().put(DATA_SCOPE,sqlString.substring(1) ); } } }/** * 是否存在注解,如果存在就获取 */ private DataScope getAnnotationLog(JoinPoint joinPoint) { Signature signature = joinPoint.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; Method method = methodSignature.getMethod(); if (method != null) { return method.getAnnotation(DataScope.class); } return null; } }

当然如果想附加不同的SQL语句,就需要对上述dataScopeFilter函数进行修改。
PS:
对于开发者而言,多看源码,看懂源码,方便我们更好的去改代码,去实现功能。

    推荐阅读