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

数据权限

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

菜单权限:
根据不同的性质的用户,显示不同的菜单。

数据权限:
设置权限,不同的用户只能访问本用户的数据,或者本部门的数据。当然对于特殊的领导可以跨部门访问数据。这些都是可以设置权限。

此代码的数据权限是基于若依框架,基于部门权限的简单数据权限设置。


实现功能

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

实现步骤
  1. 在设置儿童信息表时,添加一个字段部门id(dept_id bigint 20) ,这将作为数据过滤的条件。

基于若依框架的数据权限。_第1张图片

  1. 在MyBaits中的Mapper文件中的select语句中添加(数据过滤范围)
<sql 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
    sql>

 <select id="selectKinChildrenInfoList" parameterType="KinChildrenInfo" resultMap="KinChildrenInfoResult">
        <include refid="selectKinChildrenInfoVo"/>
         
        ${params.dataScope}
            <if test="childrenName != null  and childrenName != ''"> and CHILDREN_NAME like concat('%', #{childrenName}, '%')if>
            <if test="SEX != null  and SEX != ''"> and SEX = #{SEX}if>
            <if test="BIRTHDAY != null "> and BIRTHDAY = #{BIRTHDAY}if>
            <if test="regionCode != null  and regionCode != ''"> and REGION_CODE = #{regionCode}if>
            <if test="homeAddress != null  and homeAddress != ''"> and HOME_ADDRESS = #{homeAddress}if>
            <if test="nationId != null "> and NATION_ID = #{nationId}if>
            <if test="parentName != null  and parentName != ''"> and PARENT_NAME like concat('%', #{parentName}, '%')if>
            <if test="parentPhone != null  and parentPhone != ''"> and PARENT_PHONE = #{parentPhone}if>
       
    select>

  1. 在service层添加注解 (@DataScope)
 /**
     * 查询儿童信息列表
     * U是儿童信息表的别名
     * @param kinChildrenInfo 儿童信息
     * @return 儿童信息
     * 
     */
    @Override
    @DataScope(deptAlias = "U")
    public List<KinChildrenInfo> 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:
对于开发者而言,多看源码,看懂源码,方便我们更好的去改代码,去实现功能。

你可能感兴趣的:(若依框架,java,Spring)