若依框架學習之數據權限控制


若依框架中的數據權限控制學習記錄

若依框架中數據權限控制實現

 

 

 

 

 

  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語句中寫死。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM