@DataScope : 根据sys_role 中的 data_scope中的值,来设置数据该怎么过滤,,

data_scope 取值:

  • 1 : 不需要过滤
  • 2 : 自定义过滤 : 根据 sys_role_dept 这个表关联出来的 dept_id 过滤
  • 3 : 只显示当前所在部门 : 根据sys_user表中的 dept_id 。。当前user所属的部门过滤
  • 4: 显示当前所在部门以及他的子部门: 根据 sys_user中的dept_id ,在sys_dept中找到他和他的子部门
  • 5: 不让查看部门数据 : 只能查看自己的数据,,,可以关联 sys_user表,并设置 user表的id过滤

@DataScope 会定义两个值 ,, 第一个是 deptAlias ,,部门表的别名。。。 userAlias : user表的别名

怎么过滤的:
根据当前登录的用户的角色,,遍历每个角色的data_scope 属性,,根据这个属性,拼接sql,,,
每一次查询都会去关联 sys_dept这个表,,如果你查找的这个表,,没有和 sys_dept 直接关联的属性,,那么就需要关联 sys_user 表,,因为 sys_user 表中有dept_id 可以根据dept_id过滤数据,
不管怎么关联,,最后都会去 关联 sys_dept 并且 将查出来的部门id,,和当前用户能操作的部门,进行过滤,,, 查出来的dept_id 在当前用户能操作的部门中,,就显示

拼接的SQL:

# xxx: 代表每一个角色能操作的部门
select * from 表名 where 条件  and dept_id in (xxx   OR  xxx OR xxx)

代码:

/**
 * 根据当前用户的 role ,, 去查对应的部门,,如果你找的那个表有 dept_id 就根据那个表的 dept_id 过滤
 * 如果你找的那个表没有dept_id,,就需要关联user表,,根据user表上的dept_id过滤,,就需要关联user表,,给user表取别名,,比如查找sys_role的时候
 * @Date 2023/7/8 19:42
 * @Author cc
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DataScope {

    /**
     * 部门表的  别名
     */
    String deptAlias()  default "";

    /**
     * user 表的  别名
     */
    String userAlias() default "";
}

/**
 * 动态权限控制   : 根据数据库中 sys_role中的 data_scope的值,来动态权限
 *   1: 不设置权限控制
 *   2:  自定义权限:  根据数据库连表查出来的权限,,在sys_role_dept  中
 *   3:  只能查自己的部门,,  在sys_user中有自己的部门字段
 *   4:  不仅可以查看自己的,,还可以查看自己的子部门,,, 在 sys_dept中找出 自己部门和子部门
 *   5:  不能查看部门,,,只能看自己的数据
 *
 *   遍历角色,,根据 sys_role 判断每个角色具有的 data_scope ,拼接成 sql,
 * @Date 2023/7/8 19:45
 * @Author cc
 */
@Component
@Aspect
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";
    // BaseEntity中的params Map  中 拼接sql的key
    public static final String DATA_SCOPE = "data_scope";


    /**
     * 前置通知,,,在查询之前给  BaseEntity中的params 添加 sql 过滤
     */

    @Before("@annotation(dataScope)")
    public void before(JoinPoint joinPoint, DataScope dataScope){
            // 这个 params 可能是前端传递的
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 前端传递的是 继承BaseEntity的对象,,并且只有一个参数
        Object arg = joinPoint.getArgs()[0];
        System.out.println("arg"+arg);
        if (arg != null && arg instanceof BaseEntity){
            BaseEntity baseEntity = (BaseEntity) arg;
            baseEntity.getParams().put(DATA_SCOPE,"");
        }



        // 获取当前用户信息
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        // 判断是不是admin
        if (user.getUserId() == 1L){
            // 不用过滤
            return;
        }

        /**
         *         select * from table_name  where  ... and (xxx or  xxx or xxx)
         *
         *         xxx: 每个role限制的条件
          */
        StringBuilder sql = new StringBuilder();
        List<Role> roleList = user.getRoleList();
        for (Role role : roleList) {
            // 根据角色,生成查询的sql

            //  每个角色对应的权限是不一样的,,

            // 获取角色对应的数据权限
            String ds = role.getDataScope();

            if (DATA_SCOPE_ALL.equals(ds)){
                // 查看所有数据
                return;
            }else if (DATA_SCOPE_CUSTOM.equals(ds)){
                // 自定义数据权限  :  根据用户角色查找部门id
                sql.append(String.format(" OR  %s.dept_id in (select d.dept_id from sys_dept d,sys_role_dept rd where d.dept_id = rd.dept_id and rd.role_id =%d)",dataScope.deptAlias(),role.getRoleId()));

            }else if (DATA_SCOPE_DEPT.equals(ds)){
                // 自己当前部门
                sql.append(String.format(" OR %s.dept_id = %d",dataScope.deptAlias(),user.getDeptId()));
            }else if (DATA_SCOPE_DEPT_AND_CHILD.equals(ds)){
                // 自己部门和子部门
                sql.append(String.format(" OR %s.dept_id in (select d.dept_id from sys_dept d where d.dept_id = %d or find_in_set(%d,ancestors))",dataScope.deptAlias(),user.getDeptId(),user.getDeptId()));
            }else if(DATA_SCOPE_SELF.equals(ds)){
                // 看他传没有传 userAlias  。。 如果传了,表示那个表关联了 user表,,查找当前user表对应 userId 的数据,,如果没有 userAlias 表示没有连接 user表,
                // 没有部门权限,只能看自己的数据,,不能看部门数据
                String s = dataScope.userAlias();
                if ("".equals(s)){
                    // 没有连接 user表
                    sql.append(String.format(" OR %s.dept_id in (1=0)",dataScope.deptAlias()));
                }else{
                    // 连接了 user表
                    sql.append(String.format(" OR  %s.user_id= %d",dataScope.userAlias(),user.getUserId()));
                }
            }

            // 拼接 sql    and (xxx OR  xxx OR xxx)
            if (arg != null && arg instanceof BaseEntity){
                BaseEntity baseEntity = (BaseEntity) arg;
                baseEntity.getParams().put(DATA_SCOPE,"AND( "+ sql.substring(4) +" )");
            }

        }

    }
}

在这里插入图片描述
在这里插入图片描述

Logo

快速构建 Web 应用程序

更多推荐