若依框架中的数据权限控制学习记录

非原创,转发自博客园  若依框架学习之数据权限控制 - 迷茫的bug - 博客园

若依框架中数据权限控制实现

 

  1.  数据权限控制分为所有权限,自定义数据权限,本部门数据权限,本部门及子部门权限,仅自己五个等级的权限控制。
  2. 大致的实现思路:当用户登录之后,通过查询所登录用户的角色和权限信息,角色信息中包含datascope字段控制该用户的数据权限。
  3. 若依自定义了@Datascope注解,作用域为运行时,注解标注在查询用户列表,查询角色列表,以及查询部门列表三个方法上。当执行这三个方法就会对数据权限进行控制。用户登录就会先执行这三个方法。
  4. 若依使用AspectJ对@Datascope注解进行处理,获取注解上的别名@Datascope(deptAlias='d')用于拼接sql。拼接语句中使用的StringUtils.format()方法会将字符串中的{}使用传入的参数一一替代。
  5. 用户登录时,获取到用户的datascope字段后,传入该字段和定义的常量值匹配。匹配到对应值后,将sql语句放进一个Map(String,Object)中,键固定为dataScope,值为sql语句。传入sql语句作为值时,会将sql做一次拼接与截取(
    " AND (" + sqlString.substring(4) + ")"
    )拼接上AND( 并将sql第一个OR截取掉,效果 :and(
    d.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = 101 )
  6. 持久层通过${params.dataScope}取出sql语句拼接执行。
  7. <select id="selectRoleList" parameterType="SysRole" resultMap="SysRoleResult">
       <include refid="selectRoleVo"/>
       where r.del_flag = '0'
       <if test="roleId != null and roleId != 0">
          AND r.role_id = #{roleId}
       </if>
       <if test="roleName != null and roleName != ''">
          AND r.role_name like concat('%', #{roleName}, '%')
       </if>
       <if test="status != null and status != ''">
          AND r.status = #{status}
       </if>
       <if test="roleKey != null and roleKey != ''">
          AND r.role_key like concat('%', #{roleKey}, '%')
       </if>
       <if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
          and date_format(r.create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
       </if>
       <if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
          and date_format(r.create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
       </if>
       <!-- 数据范围过滤 -->
       ${params.dataScope}
       order by r.role_sort
    </select>
  8. 若依使用的AspectJ代码如下:
  9. package com.ruoyi.framework.aspectj;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.springframework.stereotype.Component;
    import com.ruoyi.common.annotation.DataScope;
    import com.ruoyi.common.core.domain.BaseEntity;
    import com.ruoyi.common.core.domain.entity.SysRole;
    import com.ruoyi.common.core.domain.entity.SysUser;
    import com.ruoyi.common.core.domain.model.LoginUser;
    import com.ruoyi.common.utils.StringUtils;
    import com.ruoyi.common.utils.SecurityUtils;
    
    /**
     * 数据过滤处理
     *
     * @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";
    
        @Before("@annotation(controllerDataScope)")
        public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable
        {
            clearDataScope(point);
            handleDataScope(point, controllerDataScope);
        }
    
        protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope)
        {
            // 获取当前的用户
            LoginUser loginUser = SecurityUtils.getLoginUser();
            if (StringUtils.isNotNull(loginUser))
            {
                SysUser currentUser = loginUser.getUser();
                // 如果是超级管理员,则不过滤数据
                if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
                {
                    dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
                            controllerDataScope.userAlias());
                }
            }
        }
    
        /**
         * 数据范围过滤
         *
         * @param joinPoint 切点
         * @param user 用户
         * @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(
                            " 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(" OR 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) + ")");
                }
            }
        }
    
        /**
         * 拼接权限sql前先清空params.dataScope参数防止注入
         */
        private void clearDataScope(final JoinPoint joinPoint)
        {
            Object params = joinPoint.getArgs()[0];
            if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
            {
                BaseEntity baseEntity = (BaseEntity) params;
                baseEntity.getParams().put(DATA_SCOPE, "");
            }
        }
    }

  10. 如果数据权限控制不做改变可直接在sql语句中写死。
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值