RuoYi-Vue-Plus数据权限:部门角色过滤深度解析

RuoYi-Vue-Plus数据权限:部门角色过滤深度解析

【免费下载链接】RuoYi-Vue-Plus 多租户后台管理系统 重写RuoYi-Vue所有功能 集成 Sa-Token、Mybatis-Plus、Warm-Flow工作流、SpringDoc、Hutool、OSS 定期同步 【免费下载链接】RuoYi-Vue-Plus 项目地址: https://gitcode.com/dromara/RuoYi-Vue-Plus

引言:数据权限的痛点与解决方案

在企业级应用开发中,数据权限控制是一个常见但复杂的需求。你是否遇到过这样的场景:

  • 不同部门的用户只能看到本部门的数据
  • 管理员需要查看所有数据,普通员工只能查看自己的数据
  • 多角色用户需要根据角色动态过滤数据访问范围

RuoYi-Vue-Plus通过强大的数据权限模块,提供了完善的部门角色过滤解决方案。本文将深入解析其实现原理和使用方法。

数据权限核心架构

权限控制流程图

mermaid

数据权限类型枚举

RuoYi-Vue-Plus定义了6种数据权限范围:

权限类型代码描述适用场景
全部数据权限ALL可查看所有数据系统管理员
自定数据权限CUSTOM自定义部门范围特定角色配置
部门数据权限DEPT仅本部门数据部门经理
部门及以下DEPT_AND_CHILD本部门及子部门区域负责人
仅本人数据SELF仅自己的数据普通员工
部门或本人DEPT_AND_SELF部门数据或本人数据混合权限场景

核心实现解析

数据权限注解系统

RuoYi-Vue-Plus使用注解方式声明数据权限需求:

@DataPermission({
    @DataColumn(key = "deptName", value = "dept_id")
})
public interface SysUserMapper extends BaseMapperPlus<SysUser, SysUserVo> {
    
    @DataPermission({
        @DataColumn(key = "createBy", value = "create_by")
    })
    Page<SysUserVo> selectPageUserList(@Param("page") Page<SysUser> page, @Param("query") SysUserBo user);
}

权限拦截器实现

核心拦截器PlusDataPermissionInterceptor负责SQL重写:

public class PlusDataPermissionInterceptor implements InnerInterceptor {
    
    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, 
                          Object parameter, RowBounds rowBounds, 
                          ResultHandler resultHandler, BoundSql boundSql) {
        
        // 检查是否需要忽略数据权限处理
        if (DataPermissionHelper.isIgnore()) {
            return;
        }
        
        // 获取数据权限注解
        DataPermission dataPermission = getDataPermission(ms);
        if (dataPermission == null) {
            return;
        }
        
        // 构建数据过滤SQL
        String dataFilterSql = buildDataFilterSql(dataPermission);
        if (StringUtils.isNotEmpty(dataFilterSql)) {
            // 重写原始SQL
            String newSql = originalSql + " AND " + dataFilterSql;
            resetBoundSql(boundSql, newSql);
        }
    }
}

部门角色过滤逻辑

部门过滤的核心实现在SysDataScopeServiceImpl中:

@Service("sdss")
public class SysDataScopeServiceImpl implements ISysDataScopeService {

    // 获取角色自定义权限
    @Cacheable(cacheNames = CacheNames.SYS_ROLE_CUSTOM, key = "#roleId")
    public String getRoleCustom(Long roleId) {
        List<SysRoleDept> list = roleDeptMapper.selectList(
            new LambdaQueryWrapper<SysRoleDept>()
                .select(SysRoleDept::getDeptId)
                .eq(SysRoleDept::getRoleId, roleId));
        
        return CollUtil.isNotEmpty(list) ? 
               StreamUtils.join(list, rd -> Convert.toStr(rd.getDeptId())) : "-1";
    }

    // 获取部门及以下权限
    @Cacheable(cacheNames = CacheNames.SYS_DEPT_AND_CHILD, key = "#deptId")
    public String getDeptAndChild(Long deptId) {
        List<SysDept> deptList = deptMapper.selectListByParentId(deptId);
        List<Long> ids = StreamUtils.toList(deptList, SysDept::getDeptId);
        ids.add(deptId);
        
        return CollUtil.isNotEmpty(ids) ? 
               StreamUtils.join(ids, Convert::toStr) : "-1";
    }
}

实战应用示例

场景一:部门数据过滤

假设我们需要实现一个只能查看本部门用户的功能:

@DataPermission({
    @DataColumn(key = "deptName", value = "dept_id")
})
@Mapper
public interface SysUserMapper extends BaseMapperPlus<SysUser, SysUserVo> {
    
    @Select("SELECT * FROM sys_user WHERE status = 1")
    List<SysUser> selectActiveUsers();
}

当用户执行查询时,系统会自动添加部门过滤条件:

-- 原始SQL
SELECT * FROM sys_user WHERE status = 1

-- 自动生成的SQL(用户部门ID为100)
SELECT * FROM sys_user 
WHERE status = 1 
AND dept_id IN (100)

场景二:多角色权限合并

对于拥有多个角色的用户,系统会自动合并权限:

// 用户拥有两个角色:
// - 角色A:部门权限(dept_id = 100)
// - 角色B:自定义权限(dept_id IN (200, 300))

// 最终生成的SQL条件:
dept_id IN (100, 200, 300)

场景三:忽略数据权限

在某些特殊场景下需要忽略数据权限:

public List<SysUser> getAllUsersForExport() {
    return DataPermissionHelper.ignore(() -> {
        return userMapper.selectList(null);
    });
}

高级配置与自定义

自定义数据权限服务

如果需要扩展数据权限类型,可以实现自定义服务:

@Service("customDataScope")
public class CustomDataScopeServiceImpl implements ISysDataScopeService {
    
    @Override
    public String getRoleCustom(Long roleId) {
        // 自定义逻辑
        return "1,2,3";
    }
    
    @Override
    public String getDeptAndChild(Long deptId) {
        // 自定义逻辑
        return "4,5,6";
    }
}

动态数据权限配置

通过配置文件动态调整权限行为:

ruoyi:
  data-permission:
    enabled: true
    ignore-tables: sys_config, sys_dict_data
    default-scope: DEPT

性能优化策略

缓存机制

数据权限服务使用Spring Cache进行缓存:

@Cacheable(cacheNames = CacheNames.SYS_ROLE_CUSTOM, key = "#roleId")
public String getRoleCustom(Long roleId) {
    // 数据库查询逻辑
}

批量处理优化

对于批量数据操作,使用忽略权限模式提升性能:

public void batchProcessUsers(List<Long> userIds) {
    DataPermissionHelper.ignore(() -> {
        // 批量处理逻辑,避免重复权限检查
        userMapper.updateBatch(userIds);
    });
}

常见问题与解决方案

问题1:循环依赖问题

症状:在数据权限服务中调用其他标注数据权限的方法导致死循环

解决方案

// 在数据权限服务中避免调用标注数据权限的方法
@Service("sdss")
public class SysDataScopeServiceImpl implements ISysDataScopeService {
    
    // 正确:直接使用mapper基础方法
    private final SysRoleDeptMapper roleDeptMapper;
    
    // 错误:调用标注数据权限的服务方法
    // private final ISysUserService userService;
}

问题2:权限覆盖问题

症状:多个角色权限冲突时处理不当

解决方案:系统默认采用权限合并策略,如需特殊处理可自定义权限解析器。

问题3:性能瓶颈

症状:大数据量下权限过滤导致性能下降

解决方案

  • 使用缓存减少数据库查询
  • 对大数据表进行分表分库
  • 在业务层进行数据过滤

总结与最佳实践

RuoYi-Vue-Plus的数据权限模块提供了强大而灵活的部门角色过滤能力。在实际应用中建议:

  1. 合理规划权限粒度:根据业务需求选择合适的数据范围类型
  2. 使用缓存优化:对频繁访问的权限数据进行缓存
  3. 避免循环调用:在数据权限服务中避免调用其他权限相关方法
  4. 定期审查权限:建立权限审计机制,确保权限配置的正确性
  5. 性能监控:对数据权限相关的SQL进行性能监控和优化

通过本文的深入解析,相信你已经掌握了RuoYi-Vue-Plus数据权限模块的核心原理和使用技巧。在实际项目中合理运用这些功能,可以构建出既安全又高效的企业级应用系统。

【免费下载链接】RuoYi-Vue-Plus 多租户后台管理系统 重写RuoYi-Vue所有功能 集成 Sa-Token、Mybatis-Plus、Warm-Flow工作流、SpringDoc、Hutool、OSS 定期同步 【免费下载链接】RuoYi-Vue-Plus 项目地址: https://gitcode.com/dromara/RuoYi-Vue-Plus

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值