在教育行业的数字化转型中,心理健康数据的管理往往伴随着极度复杂的行政层级。一个典型的区域性心理平台,需要同时服务于区教育局、下辖的几十所中小学、上百个年级以及数千个班级。
不同的层级意味着截然不同的数据查看权限:班主任只能看本班,心理老师能看全校,教育局专干则需要查看全区的宏观报表,且绝不能看到某个具体学生的私人测试明细。面对这种深度嵌套的树状组织架构,如果仅仅依靠最基础的用户绑定角色,系统必将在日益膨胀的业务需求中走向崩溃。
本文将探讨如何在经典的 RBAC(基于角色的访问控制)模型上进行扩展,设计一套极度严谨且灵活的数据权限引擎。
经典 RBAC 的局限性:只有功能权限,没有数据边界
基础的 RBAC 架构通常包含三层核心:User(用户) -> Role(角色) -> Permission(权限点)。
例如,分配一个“班主任”角色,该角色拥有“查看报表”的菜单权限。
但这在心理SaaS中是远远不够的。当两个人都拥有“查看报表”的功能权限时,张老师应该只能查阅初一(1)班的数据,而李老师只能查阅初一(2)班的数据。如果不对数据边界进行拦截,系统就会出现极其严重的越权访问漏洞,导致学生心理隐私的大规模泄露。
为了解决这个问题,我们需要引入扩展模型:RBAC + 数据作用域(Data Scope)。
引入树状组织架构字典
组织架构树可以采用邻接表、路径枚举或闭包表。选型要结合层级深度、变更频率和查询负载,递归查询是否成为瓶颈应由执行计划与压测判断。
路径枚举和闭包表是两种可选方案。以路径枚举为例,可以在机构表 sys_dept 中保存 dept_path:
- 区教育局:
/100/ - 某市第一中学:
/100/101/ - 初一年级:
/100/101/1011/ - 初一(1)班:
/100/101/1011/10111/
查询第一中学下属班级时,可使用 WHERE dept_path LIKE '/100/101/%' 这一类前缀条件。是否利用索引取决于数据库、排序规则和索引设置,应通过执行计划验证。
数据作用域(Data Scope)的设计与拦截
有了高效的树状字典后,我们需要在角色配置中增加“数据权限类型”字段,常见的设计分为以下几档:
- 全部数据权限:拥有全库最高视野,通常仅供超级管理员使用。
- 本机构及以下数据权限:这是最核心的规则。比如教育局专干,查询范围锁定为其绑定的
dept_id及其子路径。 - 仅本机构数据权限:只能查看当前层级的数据,不能向下穿透。
- 自定义数据权限:支持跨机构勾选。例如某个心理名师,可能同时负责三所不同高中的心理辅导,需要单独绑定这三所学校的节点。
后端拦截器(Interceptor)的实现机制
研发团队绝不能指望前端通过传递参数来过滤数据,任何由客户端发起的过滤条件都是极度不可靠且极易被黑客篡改的。
数据隔离必须在后端的核心框架层完成。可以通过 AOP(面向切面编程)结合 MyBatis 的拦截器插件来实现:
当后端接收到一个分页查询学生心理档案的请求时,AOP 会拦截该请求,获取当前登录用户的 Token 解析出其数据作用域。随后,SQL 拦截器会在原有的查询语句末尾,动态拼接上 AND deptid IN (SELECT id FROM sysdept WHERE dept_path LIKE '当前用户机构路径%')。
统一拦截有助于减少漏写权限条件,但仍需覆盖导出、详情、批量查询、后台任务和自定义 SQL,并使用跨机构访问测试检查隔离是否有效。
特殊的隐私隔离墙:统计聚合与明细穿透
在教育系统的心理数据管控中,还有一个极其特殊的红线:高级别的行政领导(如教育局局长)需要看全区的统计大屏,但绝对不能向下穿透查看到某个特定学生名为“张三”的抑郁症测试得分。
这意味着系统需要在 API 网关层进一步区分“聚合接口”和“明细接口”。对于明细接口,必须在拦截器中加入反向约束,当用户角色不是心理干预专员或直系辅导员时,强制抛出无权访问的异常,或是对数据进行高度脱敏(如姓名打码、具体得分隐藏为等级区间)。
总结
嵌套组织的权限设计,要同时回答“能做什么”和“能看哪些数据”。组织树、数据作用域和统一校验需要配合最小授权、审计与越权测试;任何单一组件都不足以承担全部安全责任。
