若依如何实现数据范围过滤的

若依如何实现数据范围过滤的

若依源码分析-----数据范围过滤
通过${params.dataScope}在需要进行数据范围过滤的地方拼接一个sql语句。

or d.dept_id in (select dept_id from sys_role_dept where role_id ={rolelist})

我们看一下若依是如何实现的

首先在需要进行数据范围过滤的地方加上注解 @DataScope(deptAlias = “d”)

比如下面server层获取部门清单

/**
 * 查询部门管理数据
 * 
 * @param dept 部门信息
 * @return 部门信息集合
 */
@Override
// 设置表的别名为 d
@DataScope(deptAlias = "d")
public List<SysDept> selectDeptList(SysDept dept)
{
    return deptMapper.selectDeptList(dept);
}

下面是重点,通过切面动态拼接params。dataScope参数,从而改变sql的查询范围。

该切面是发生在@DataScope标注的方法之前进行切入和处理

/**
 * 数据过滤处理
 *
 * @author sj
 */
@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.sj.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;
        }
        // 获取当前的用户
        LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
        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))
            {
                // dept_id等于本本部门的id或者dept_id在祖级列表里面
                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 ");
                }
            }
        }
        
        // 将sqlString转换为String且当不为空时
        if (StringUtils.isNotBlank(sqlString.toString()))
        {
            // 获取连接点的参数,
            Object params = joinPoint.getArgs()[0];
            // 如果参数不为空并且是一个实体
            if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
            {
                // 将参数转换为实体
                BaseEntity baseEntity = (BaseEntity) params;
                // 将拼接的Sql语句放到参数列表
                baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
            }
        }
    }

    /**
     * 是否存在注解,如果存在就获取
     */
    private DataScope getAnnotationLog(JoinPoint joinPoint)
    {
        // 获取封装了签名信息的对象,在该对象中可以获取到目标方法名,所属类的class等信息
        Signature signature = joinPoint.getSignature();
        // 将签名对象转换为方法签名对象
        MethodSignature methodSignature = (MethodSignature) signature;
        // 获取到目标方法
        Method method = methodSignature.getMethod();
        // 如果目标方法不为空则返回目标方法上的注解
        if (method != null)
        {
            return method.getAnnotation(DataScope.class);
        }
        // 否则返回空
        return null;
    }
}

// 作为前置知识需要了解角色管理页面中,可以配置下面几种数据范围
 /**
     * 全部数据权限
     */
    public static final String DATA_SCOPE_ALL = "1";
 /**
     * 自定数据权限
     */
    public static final String DATA_SCOPE_CUSTOM = "2";


查询 部门角色对应表中,用户具备的角色可以管理那些部门
 OR d.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {rolelist} )    


/**
     * 部门数据权限
     */
    public static final String DATA_SCOPE_DEPT = "3";


查询部门编号=用户所在部门编号的数据
OR {}.dept_id = {}  

  /**
     * 部门及以下数据权限
     */
    public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";


查询部门和子部门的权限

    /**
     * 仅本人数据权限
     */
    public static final String DATA_SCOPE_SELF = "5";
    
    if (StringUtils.isNotBlank(userAlias))
{
    sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
}
else
{
    // 数据权限为仅本人且没有userAlias别名不查询任何数据
    sqlString.append(" OR 1=0 ");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值