底座开发指南
萌新必读
简介
功能列表
快速启动(后端项目)
快速启动(前端项目)
接口文档
热代码加载
迁移模式(适合新项目)
删除功能(以租户为例)
表结构变更(版本升级)
内网穿透
达梦数据库专属
后端手册
新建服务
代码生成【单表】(新增功能)
代码生成(树表)
功能权限·
数据权限
用户体系
三方登陆
OAuth 2.0(SSO 单点登录)
SaaS 多租户【字段隔离】
SaaS 多租户【数据库隔离】
WebSocket 实时通信
异常处理(错误码)
参数校验
分页实现
VO 对象转换、数据翻译
文件存储(上传下载)
Excel 导入导出
操作日志、访问日志、异常日志
MyBatis 数据库
MyBatis 联表&分页查询
多数据源(读写分离)
Redis 缓存
本地缓存
异步任务
分布式锁
幂等性(防重复提交)
请求限流(RateLimiter)
HTTP 接口签名(防篡改)
单元测试
验证码
工具类 Util
数据库文档
微服务手册
微服务调试(必读)
注册中心 Nacos
配置中心 Nacos
服务网关 Spring Cloud Gateway
服务调用 Feign
定时任务 XXL Job
消息队列(内存)
消息队列(Redis)
消息队列(RocketMQ)
消息队列(RabbitMQ)
消息队列(Kafka)
消息队列(Cloud)
分布式事务 Seata
服务保障 Sentinel
工作流手册
工作流演示
功能开启
工作流(达梦适配)
审批接入(流程表单)
审批接入(业务表单)
流程设计器(BPMN)
流程设计器(钉钉、飞书)
选择审批人、发起人自选
会签、或签、依次审批
流程发起、取消、重新发起
审批通过、不通过、驳回
审批加签、减签
审批转办、委派、抄送
执行监听器、任务监听器
流程表达式
流程审批通知
大屏手册
报表设计器
大屏设计器
支付手册
功能开启·
支付宝支付接入
微信公众号支付接入
微信小程序支付接入
支付宝、微信退款接入
会员手册
功能开启··
微信公众号登录
微信小程序登录
微信小程序订阅消息
微信小程序码
会员用户、标签、分组
会员等级、积分、签到
商城手册
商城演示
功能开启···
商城装修
在线客服
【商品】商品分类
【商品】商品属性
【商品】商品 SPU 与 SKU
【商品】商品评价
【交易】购物车
【交易】交易订单
【交易】售后退款
【交易】快递发货
【交易】门店自提
【交易】分销返佣
【营销】优惠劵
【营销】拼团活动
【营销】秒杀活动
【营销】砍价活动
【营销】满减送
【营销】限时折扣
【营销】内容管理
【统计】会员、商品、交易统计
ERP 手册
ERP 演示
【功能开启】
【产品】产品信息、分类、单位
【库存】产品库存、库存明细
【库存】其它入库、其它出库
【库存】库存调拨、库存盘点
【采购】采购订单、入库、退货
【销售】销售订单、出库、退货
【财务】采购付款、销售收款
CRM手册
CRM 演示
【功能开启】·
【线索】线索管理
【客户】客户管理、公海客户
【商机】商机管理、商机状态
【合同】合同管理、合同提醒
【回款】回款管理、回款计划
【产品】产品管理、产品分类
【通用】数据权限
【通用】跟进记录、待办事项
AI大模型手册
AI 大模型演示
功能开启-
AI 聊天对话
AI 绘画创作
AI 音乐创作
AI 写作助手
AI 思维导图
【模型接入】OpenAI
【模型接入】通义千问
【模型接入】LLAMA
【模型接入】文心一言
【模型接入】DeepSeek
【模型接入】智谱 GLM
【模型接入】讯飞星火
【模型接入】微软 OpenAI
【模型接入】谷歌 Gemini
【模型接入】Stable Diffusion
【模型接入】Midjourney
【模型接入】Suno
公众号手册
【功能开启】-
公众号接入
公众号粉丝
公众号标签
公众号消息
自动回复
公众号菜单
公众号素材
公众号图文
公众号统计
系统手册
短信配置
邮件配置
站内信配置
数据脱敏
敏感词
地区 & IP 库
运维手册
开发环境
Linux 部署
Docker 部署
Jenkins 部署
HTTPS 证书
服务监控
前端手册 Vue 3.x
开发规范
菜单路由
Icon 图标
字典数据
系统组件
通用方法
配置读取
CRUD 组件
国际化
IDE 调试
代码格式化
前端手册 Vue 2.x
开发规范·
菜单路由·
Icon 图标·
字典数据·
系统组件·
通用方法·
配置读取·
本文档使用「觅思文档专业版」发布
-
+
首页
数据权限
数据权限,实现指定用户可以操作指定范围的数据。例如说,针对员工信息的数据权限:  上述的这个示例,使用硬编码是可以实现的,并且也非常简单。但是,在业务快速迭代的过程中,类似这种数据需求会越来越多,如果全部采用硬编码的方式,无疑会给我们带来非常大的开发与维护成本。 因此,项目提供 dtpc-spring-boot-starter-biz-data-permission (opens new window)技术组件,只需要少量的编码,无需入侵到业务代码,即可实现数据权限。 ## 1. 实现原理 dtpc-spring-boot-starter-biz-data-permission 技术组件的实现原理非常简单,每次对数据库操作时,他会自动拼接 WHERE data_column = ? 条件来进行数据的过滤。 例如说,查看员工信息的功能,对应 SQL 是 SELECT * FROM system_users,那么拼接后的 SQL 结果会是:  明白了实现原理之后,想要进一步加入理解,后续可以找时间 Debug 调试下 MyBatis Plus 的 DataPermissionInterceptor 类的这三个方法: #processSelect(...) 方法:处理 SELECT 语句的 WHERE 条件。 #processUpdate(...) 方法:处理 UPDATE 语句的 WHERE 条件。 #processDelete(...) 方法:处理 DELETE 语句的 WHERE 条件。 主要还是基于 MyBatis Plus 的 [数据权限插件](http://https://baomidou.com/plugins/data-permission/ "数据权限插件") 具体的条件生成,可见项目的 DataPermissionRuleHandler 类。 ## 2. 基于部门的数据权限 项目内置了基于部门的数据权限,支持 5 种数据范围: 1. 全部数据权限:无数据权限的限制。 2. 指定部门数据权限:根据实际需要,设置可操作的部门。 3. 本部门数据权限:只能操作用户所在的部门。 4. 本部门及以下数据权限:在【本部门数据权限】的基础上,额外可操作子部门。 5. 仅本人数据权限:相对特殊,只能操作自己的数据。 2.1 后台配置 可通过管理后台的 [系统管理 -> 角色管理] 菜单,设置用户角色的数据权限。  2.2 字段配置 每个 Maven Module, 通过自定义 DeptDataPermissionRuleCustomizer (opens new window)Bean,配置哪些表的哪些字段,进行数据权限的过滤。以 dtpc-module-system 模块来举例子,代码如下: @Configuration(proxyBeanMethods = false) public class DataPermissionConfiguration { @Bean public DeptDataPermissionRuleCustomizer sysDeptDataPermissionRuleCustomizer() { return rule -> { // dept 基于部门的数据权限 rule.addDeptColumn(AdminUserDO.class); // WHERE dept_id = ? rule.addDeptColumn(DeptDO.class, "id"); // WHERE id = ? // user 基于用户的数据权限 rule.addUserColumn(AdminUserDO.class, "id"); // WHERE id = ? // rule.addUserColumn(OrderDO.class); // WHERE user_id = ? }; } } 注意,数据库的表字段必须添加: 基于【部门】过滤数据权限的表,需要添加部门编号字段,例如说 dept_id 字段。 基于【用户】过滤数据权限的表,需要添加部门用户字段,例如说 user_id 字段。 ## 3. @DataPermission 注解 @DataPermission (opens new window)数据权限注解,可声明在类或者方法上,配置使用的数据权限规则。 ① enable 属性:当前类或方法是否开启数据权限,默认是 true 开启状态,可设置 false 禁用状态。 也就是说,数据权限默认是开启的,无需添加 @DataPermission 注解 也就是说,数据权限默认是开启的,无需添加 @DataPermission 注解 也就是说,数据权限默认是开启的,无需添加 @DataPermission 注解 使用示例如下,可见 UserProfileController 类: <span style="font-family:楷体">`// UserProfileController.java @GetMapping("/get") @Operation(summary = "获得登录用户信息") @DataPermission(enable = false) // 关闭数据权限,避免只查看自己时,查询不到部门。 public CommonResult<UserProfileRespVO> profile() { // .. 省略代码 if (user.getDeptId() != null) { DeptDO dept = deptService.getDept(user.getDeptId()); resp.setDept(UserConvert.INSTANCE.convert02(dept)); } // .. 省略代码 } `</span> ② includeRules 属性,配置生效的 DataPermissionRule (opens new window)数据权限规则。例如说,项目里有 10 种 DataPermissionRule 规则,某个方法只想其中的 1 种生效,则可以使用该属性。 ③ excludeRules 属性,配置排除的 DataPermissionRule (opens new window)数据权限规则。例如说,项目里有 10 种 DataPermissionRule 规则,某个方法不想其中的 1 种生效,则可以使用该属性。 ## 4. 自定义的数据权限规则 如果想要自定义数据权限规则,只需要实现 DataPermissionRule (opens new window)数据权限规则接口,并声明成 Spring Bean 即可。需要实现的只有两个方法: public interface DataPermissionRule { /** * 返回需要生效的表名数组 * 为什么需要该方法?Data Permission 数组基于 SQL 重写,通过 Where 返回只有权限的数据 * * 如果需要基于实体名获得表名,可调用 {@link TableInfoHelper#getTableInfo(Class)} 获得 * * @return 表名数组 */ Set<String> getTableNames(); /** * 根据表名和别名,生成对应的 WHERE / OR 过滤条件 * * @param tableName 表名 * @param tableAlias 别名,可能为空 * @return 过滤条件 Expression 表达式 */ Expression getExpression(String tableName, Alias tableAlias); } <span style="font-family:楷体">#getTableNames() 方法:哪些数据库表,需要使用该数据权限规则。 - #getExpression(...) 方法:当操作这些数据库表,需要额外拼接怎么样的 WHERE 条件。 下面,艿艿带你写个自定义数据权限规则的示例,它的数据权限规则是: - 针对 system_dict_type 表,它的创建人 creator 要是当前用户。 - 针对 system_post 表,它的更新人 updater 要是当前用户。 - 具体实现代码如下:</span> <span style="font-family:楷体">package cn.iocoder.yudao.module.system.framework.datapermission; import cn.iocoder.yudao.framework.datapermission.core.rule.DataPermissionRule; import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import com.google.common.collect.Sets; import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.LongValue; import net.sf.jsqlparser.expression.operators.relational.EqualsTo; import org.springframework.stereotype.Component; import java.util.Set; @Component // 声明为 Spring Bean,保证被 yudao-spring-boot-starter-biz-data-permission 组件扫描到 public class DemoDataPermissionRule implements DataPermissionRule { @Override public Set<String> getTableNames() { return Sets.newHashSet("system_dict_type", "system_post"); } @Override public Expression getExpression(String tableName, Alias tableAlias) { Long userId = SecurityFrameworkUtils.getLoginUserId(); assert userId != null; switch (tableName) { case "system_dict_type": return new EqualsTo(MyBatisUtils.buildColumn(tableName, tableAlias, "creator"), new LongValue(userId)); case "system_post": return new EqualsTo(MyBatisUtils.buildColumn(tableName, tableAlias, "updater"), new LongValue(userId)); default: return null; } } } </span> ① 启动前端 + 后端项目。 ② 访问 [系统管理 -> 字典管理] 菜单,查看 IDEA 控制台,可以看到 system_dict_type 表的查询自动拼接了 AND creator = 1 的查询条件。  ② 访问 [系统管理 -> 岗位管理] 菜单,查看 IDEA 控制台,可以看到 system_post 表的查询自动拼接了 AND updater = 1 的查询条件。  ## 5. 如何忽略数据权限 可以使用 DataPermissionUtils 的 #executeIgnore(...) 方法,设置忽略数据权限。 具体的案例,可以通过 IDEA 查找下项目里,哪些地方调用了这个方法噢! ## 6. 社区贡献的数据权限规则
何加华
2024年8月26日 14:18
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
Word文件
PDF文档
PDF文档(打印)
分享
链接
类型
密码
更新密码
有效期