菜单少一个通常一眼就能发现,数据少几台设备却难得多。用户看到的是“这张图不对”,研发拿管理员身份一查又有结果,讨论很容易变成来回加权限。
我更习惯固定一个用户、一项应用、当前组织和一个资源,从实际查询的范围往回查。数据可见性由几层条件共同决定,任何一层不包含它,最后都不会出现。
授权来源合并,访问范围收窄
用一个简化例子:用户直接得到 A,通过用户组得到 B,通过组织规则得到 C,用户授权集合就是 A、B、C。应用只允许访问 A、B、D,当前业务范围只有 A、C、D,最终可见的是三个集合的交集,只剩 A。
direct = {"A"}
groups = {"B"}
org_rules = {"C"}
application = {"A", "B", "D"}
business_scope = {"A", "C", "D"}
user_grants = direct | groups | org_rules
visible = user_grants & application & business_scope
assert visible == {"A"}这份运算不包含显式拒绝、临时授权和策略优先级。如果系统支持这些能力,就得按自己的决策规则计算,不能把一个集合公式套到所有平台。
“用户已经授权”只说明某种来源存在,不保证应用范围也包含这份资源。后台服务身份能拿到数据,也不代表普通用户应该拿到同样的结果。
查询在哪个阶段受限
权限条件应进入实际查询,在排序、分页和聚合之前生效。分页完成才删掉无权记录,会导致每页条数和总数对不上;汇总完成再过滤,甚至可能从差值推回不该看到的数据。
资源表按租户收窄,主体授权和应用绑定采用存在性判断。同一设备经过多种授权获得时,只保留一份资源,不能连接出重复记录,再让业务层去重。
列表、count、统计与导出复用相同的范围定义。不能列表走用户授权,导出却改用宽权限服务身份,否则界面看起来正确,下载内容仍可能越权。
授权索引有自己的更新时间
资源多时,每次把全部授权拉到前端做集合运算并不合适。可以在查询侧关联,也可以构建有效授权索引。后者降低查询成本,却增加了组成员变化、撤权和资源迁移后的同步责任。
索引不能只处理新增授权。撤回一个来源后,还要检查是否有其他来源继续允许;所有依据都消失,资源才应不可见。缓存与索引需要记录策略版本或有效期,让一次结果能对应到明确的授权状态。
数据库行级策略可以增加约束,但不能忽略实际连接身份。表拥有者与特权角色可能具有不同执行行为,连接池复用时也必须按事务设置并清理主体上下文。上一位用户的状态不能留给下一次查询。
排查记录要能重复得到同一个结果
一次记录包含用户、应用、组织、资源、请求时间和策略版本。逐层查应用集合、业务范围、主体授权及实际查询身份;这些符合以后,才继续核对缓存和同步。
管理员可以查看哪层条件缺失,普通用户的提示则遵守资源隐藏规则。诊断信息不应变成枚举其他组织资源的入口。
验收覆盖列表与导出的集合一致、重复授权不增加重复行、撤回部分来源仍保留有效访问,以及全部撤销后在约定窗口内失效。结果能按这些条件解释,排查就不必靠反复扩大权限碰运气。