当前位置: 首页 > news >正文

RuoYi框架二次开发系列(二)数据权限深度定制、源码解析与实战落地

在上一篇《RuoYi二次开发常用技巧与功能拓展》中,我们讲解了基础开发规范、CRUD提效技巧与通用功能拓展。而在企业级后台系统中,功能权限只解决“能不能点”,数据权限才解决“能不能看”。
绝大多数OA、ERP、政务、国资、供应链系统的核心安全需求,都是行级数据隔离:普通员工只能看自己的数据、部门主管看本部门数据、管理员看全量数据。
本文为系列第二篇,深度拆解 RuoYi 数据权限底层原理、五种默认权限规则、自定义数据权限开发、特殊业务场景适配、常见Bug与终极避坑方案,所有代码均可直接用于生产环境。

一、先搞懂:RuoYi 功能权限 vs 数据权限

很多新手开发者容易混淆两种权限,导致权限配置混乱、数据越权等问题,二者核心区别如下:

1.1 功能权限(按钮/菜单权限)
控制用户能否访问某个接口、页面、按钮,属于「操作权限」。
实现方式:基于 @PreAuthorize 注解、菜单权限标识控制,例如@PreAuthorize(“hasPermission(‘biz:goods:list’)”)。
特点:全局固定,与数据本身无关,有权限就能操作全部数据。

1.2 数据权限(行级权限)
控制用户能查询、操作哪些数据,属于「数据范围权限」。
实现方式:MyBatis 拦截器动态拼接 SQL 条件,自动过滤数据,无需手动写判断。
特点:同接口、同权限的不同用户,查询结果不同,实现数据隔离。

二、RuoYi 原生五种数据权限规则(核心基础)

RuoYi 内置五种开箱即用的数据权限范围,也是企业项目最常用的规则,绑定在角色维度,一个角色对应一种数据范围。

权限类型常量标识权限说明适用场景
全部数据权限data_scope=1可查询所有数据,无过滤超级管理员、平台总管理员
自定义数据权限data_scope=2手动指定可查看的部门列表跨部门审批、专项管理员
本部门数据权限data_scope=3仅查询当前所属部门数据部门主管、部门运营
本部门及以下data_scope=4查询当前部门+下级所有部门数据多级部门管理层、区域负责人
仅本人数据权限data_scope=5只查询自己创建的数据普通员工、基础业务人员

核心知识点:数据权限是角色级配置,一个用户多个角色时,权限会取并集,以最大数据范围为准。

三、底层原理:数据权限如何自动生效?

RuoYi 数据权限核心基于 MyBatis 插件拦截器 实现,无需开发者手动拼接 SQL,全程自动处理。

3.1 执行流程

  1. 用户登录,框架缓存当前用户角色、部门、数据范围配置;
  2. 业务 Mapper 执行查询 SQL 时,触发数据权限拦截器 DataScopeInterceptor;
  3. 拦截器判断当前接口是否需要数据权限过滤;
  4. 根据角色对应的 data_scope 类型,动态拼接 WHERE 过滤条件;
  5. MyBatis 执行拼接后的 SQL,返回过滤后的数据集。

3.2 默认过滤规则源码逻辑
框架默认依赖数据表的 create_by(本人数据)、dept_id(部门数据)两个字段实现过滤,这也是上一篇文章强调业务表必须携带通用字段的核心原因。
简单对应逻辑:

  • 仅本人:create_by = 当前登录用户名
  • 本部门:dept_id = 当前用户部门ID
  • 本部门及下级:dept_id IN (当前部门及所有子部门ID)

四、标准数据权限快速落地(零代码开启)

很多开发者不知道:RuoYi 新增业务模块,无需写一行代码,即可开启数据权限,只需遵循规范配置即可。
4.1 前置条件
业务数据表必须包含两个核心字段:

  • create_by varchar(64):创建人账号
  • dept_id bigint:数据所属部门ID
    通过代码生成器生成的代码,会自动适配数据权限拦截规则。

4.2 开启方式
在业务 Mapper 的 List 查询方法上,添加数据权限注解:

/** * 查询商品列表 */ @DataScope List<BizGoods>selectBizGoodsList(BizGoods bizGoods);

仅此一行注解,自动拥有全部五种数据权限过滤能力。

4.3 后台角色配置
系统管理 > 角色管理 > 数据权限,选择对应权限范围,保存后立即生效,无需重启服务。

五、高阶实战:自定义数据权限场景开发

原生五种规则无法覆盖所有业务,实战中高频出现:按片区、按门店、按项目、按自定义维度过滤数据。下面讲解企业最常用的自定义字段数据权限通用方案,不改动源码、完全拓展实现。

5.1 业务场景
例如:门店管理系统,不同区域经理只能查看自己负责的门店数据,不再以部门为维度,而是以 shop_id 门店ID作为数据隔离维度。

5.2 实现思路(AOP+自定义注解)

  1. 自定义数据权限注解,标记需要门店权限过滤的接口;
  2. 用户维度存储可操作的门店ID集合;
  3. 通过 MyBatis 拦截器或 AOP 动态拼接 SQL 过滤条件;
  4. 实现基于门店的行级数据隔离。

5.3 完整可落地代码
第一步:自定义注解

@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface ShopDataScope{}

第二步:自定义数据权限拦截器,继承原生拦截器拓展逻辑,重写过滤规则,支持 shop_id 过滤。
核心逻辑:获取当前用户已分配门店列表,拼接 SQL:shop_id IN (1,2,3)。

第三步:Mapper 方法添加注解

@ShopDataScope List<BizShop>selectBizShopList(BizShop bizShop);

至此,完成自定义维度的数据权限隔离,完全解耦框架源码,支持后续无限拓展。

六、特殊业务场景适配方案

6.1 详情、编辑、删除接口数据权限控制
原生数据权限仅对列表查询生效,详情、修改、删除接口默认无过滤,会出现「看不到列表,但能通过ID编辑别人数据」的越权漏洞。
解决方案:
在 Service 层统一校验数据权限,通过工具类判断当前用户是否有权操作该条数据,无权限直接抛出异常。

// 校验当前用户是否拥有该数据操作权限 DataScopeUtils.checkDataPermission(bizGoods.getCreateBy(), bizGoods.getDeptId());

6.2 超级管理员数据权限放行
框架默认超级管理员自动放行所有数据权限,无需手动处理,自定义拦截器需保留该逻辑,避免管理员数据被过滤。

6.3 多角色数据权限冲突解决
用户拥有多个角色时,遵循最大权限原则:全部权限 > 自定义 > 部门及以下 > 部门 > 本人。

七、数据权限高频Bug与避坑指南

坑1:新增数据后自己看不到
原因:业务表未自动填充 dept_id、create_by 字段

解决:严格使用框架自带的自动填充规则,勿手动insert字段为空

  • 坑2:数据权限不生效
    原因1:Mapper查询方法未加 @DataScope 注解

原因2:测试账号为超级管理员(默认全量数据)

原因3:角色数据权限配置为「全部数据」

  • 坑3:关联查询、多表查询数据权限失效
    原因:原生拦截器仅针对单表字段过滤

解决:多表查询手动拼接数据权限条件,或自定义拦截器适配关联表

  • 坑4:分页总数与列表数据不一致
    原因:分页count查询未走数据权限拦截

解决:保证count查询和list查询均被数据权限拦截

  • 坑5:导出数据越权
    原因:导出接口未添加数据权限注解

解决:导出 Mapper 方法统一添加 @DataScope

八、生产级最佳实践总结

  1. 所有业务表必带 dept_id、create_by,这是数据权限的基石;
  2. 所有业务列表查询必加 @DataScope,统一开启数据过滤;
  3. 单表查询优先使用原生规则,不重复造轮子;
  4. 特殊维度使用自定义注解+AOP拓展,坚决不改源码;
  5. 增删改详情接口必须手动权限校验,杜绝越权漏洞;
  6. 导出、批量操作接口优先适配数据权限,保障数据安全。

九、下篇预告

下一篇为系列第三篇:RuoYi 第三方功能集成实战(OSS文件上传、短信验证码、微信登录、支付对接),全程无坑、可直接复制上线的生产级集成方案。

http://www.jsqmd.com/news/1185657/

相关文章:

  • 游戏AI开发实战:基于Behaviac行为树框架构建智能NPC
  • 模板驱动型文档自动化:让高频结构化文档像流水线一样稳定输出
  • PyTorch Wrapper:可调试、可复现、可扩展的工业级训练骨架
  • 亲身探访上海真力时官方售后服务中心|网点地址与官方客服热线(2026年7月最新) - 亨得利官方服务中心
  • 如何快速入门Awesome-Prompt-Adapter-Learning-for-VLMs-CLIP:10个核心概念解析
  • 锂离子电池组主动平衡技术解析与BQ25887应用
  • 深入技术分析:SESR-M7的线性过参数化CNN架构如何实现高效超分辨率
  • GPT-3.5 API调用实战:问题解析与优化策略
  • 2026年杭州本地质量好的压力容器生产厂家选型指南 - 热点品牌推荐
  • CAD笔记
  • Marauders Map开源贡献指南:如何参与项目开发与功能改进
  • C++构建企业级面试考务系统:架构、调度算法与工程实践
  • 深度解析Cursor设备指纹机制与三种绕过方案实战
  • MATLAB信号波形生成工具包:正弦/方波/三角波/脉冲/衰减振荡一键绘图
  • 貌似目前已经可以正常关闭图片类型的广告了
  • Run-On-Arch GitHub Action架构原理:深入理解QEMU容器化实现
  • 卡地亚官方换电池价格查询|完整热线和维修地址权威信息公告(2026年7月最新) - 卡地亚服务中心
  • Unity3D AI Navigation系统中文详解与实战技巧
  • 基于OpenGL与TensorRT的PC端实时人脸美颜技术解析
  • 基于OpenAI Codex的PR代码自动审查实践指南
  • MATLAB神经网络与优化算法实战:从基础到AI应用开发
  • 2026年门窗五金实力供应商:聚焦综合竞争力与源头制造优势 - 甄选服务推荐
  • ADC 采样数据乱跳?分享我用了多年的滤波函数
  • DeepSeek mHC技术:革新LLM残差连接架构的突破
  • 2026年有没有不用下载App的转换推荐 亲测好用的方法 - 图片处理研究员
  • 梦笔记20260714
  • python核心语法
  • 卡地亚中国官方售后服务中心|服务热线及全部维修详细地址权威信息声明(2026年7月最新) - 卡地亚官方售后中心
  • 元初混沌 6G 全域通感一体化体系架构 第一卷二阶第二十四篇 组网长期周期性节律演化分析
  • C++实现电影院购票系统:面向对象设计与核心算法实践