推荐

subject与subject_member的关系

y yasepix · 2026-09-19 20:53 · 68 浏览
这是个好问题。要给出靠谱的回答,我得先看清楚这个表在你们项目里到底怎么定义的、怎么用的,而不是凭空猜。让我先查一下代码和建表语句。 找到了不少代码。让我读关键文件:实体定义、建表语句,以及它在权限体系里的核心用法(SnapshotBuilder 看起来是权限快照构建逻辑)。 关键信息已经很清楚了。让我再确认下 `auth_subject` 这张表怎么跟 `sys_user` 挂上钩,以及主体类型注册表的设计,这样解释才准确。 读完代码,这个设计其实很清晰了。先给你一张解析链路图,再讲为什么这么设计。 <svg viewBox="0 0 680 466" width="100%" role="img"> <title>auth_grant 到 sys_user 的授权解析链路</title> <desc>授权经 auth_subject 主体,沿 auth_subject_member 递归展开,最终在 type=user 时落到 sys_user</desc> <defs> <marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"> <path d="M2 1L8 5L2 9" fill="none" stroke="context-stroke" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> </marker> </defs> <g> <rect x="240" y="30" width="200" height="56" rx="8" fill="#E6F1FB" stroke="#185FA5" stroke-width="0.5"/> <text x="340" y="52" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="500" fill="#0C447C">auth_grant 授权</text> <text x="340" y="72" text-anchor="middle" dominant-baseline="central" font-size="12" fill="#185FA5">subject_id → auth_subject.id</text> </g> <g> <rect x="240" y="150" width="200" height="64" rx="8" fill="#EEEDFE" stroke="#534AB7" stroke-width="0.5"/> <text x="340" y="174" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="500" fill="#26215C">auth_subject 授权主体</text> <text x="340" y="194" text-anchor="middle" dominant-baseline="central" font-size="12" fill="#534AB7">subject_type + subject_id</text> </g> <g> <rect x="50" y="290" width="270" height="74" rx="8" fill="#E1F5EE" stroke="#0F6E56" stroke-width="0.5"/> <text x="185" y="314" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="500" fill="#04342C">auth_subject_member 成员关系</text> <text x="185" y="334" text-anchor="middle" dominant-baseline="central" font-size="12" fill="#0F6E56">group_subject_id ↔ member_id</text> <text x="185" y="352" text-anchor="middle" dominant-baseline="central" font-size="12" fill="#0F6E56">递归展开 · 带环检测 / 深度上限</text> </g> <g> <rect x="400" y="390" width="240" height="56" rx="8" fill="#EAF3DE" stroke="#3B6D11" stroke-width="0.5"/> <text x="520" y="412" text-anchor="middle" dominant-baseline="central" font-size="14" font-weight="500" fill="#173404">sys_user 用户(叶子)</text> <text x="520" y="432" text-anchor="middle" dominant-baseline="central" font-size="12" fill="#3B6D11">type=user 时 subject_id = sys_user.id</text> </g> <line x1="340" y1="86" x2="340" y2="148" stroke="#5F5E5A" stroke-width="1.5" marker-end="url(#arrow)"/> <text x="352" y="120" font-size="12" fill="#444441">授权指向主体</text> <path d="M270 214 L185 288" fill="none" stroke="#0F6E56" stroke-width="1.5" marker-end="url(#arrow)"/> <text x="150" y="262" font-size="12" fill="#04342C">非用户类型向下展开</text> <path d="M60 300 C 40 230, 150 200, 240 180" fill="none" stroke="#0F6E56" stroke-width="1.5" marker-end="url(#arrow)"/> <text x="40" y="240" font-size="12" fill="#04342C">member_id 回指 auth_subject(递归)</text> <path d="M392 206 L510 388" fill="none" stroke="#3B6D11" stroke-width="1.5" marker-end="url(#arrow)"/> <text x="420" y="300" font-size="12" fill="#173404">type=user 命中用户</text> </svg> 我先加载图示模块: 先直接回答你的核心疑问:**`auth_subject_member` 并不是"不跟 `sys_user` 关联",而是通过 `auth_subject` 这一层间接关联。** 它的 `member_id` 指向的是 `auth_subject.id`,不是 `sys_user.id`;只有当某个 subject 是"用户类型(type=1)"时,`auth_subject.subject_id` 才等于 `sys_user.id`。所以链路是 `auth_subject_member → auth_subject → (type=1) → sys_user`。 ## 这张表是干什么的 它是一张**主体成员关系边表**,建模的是"授权主体之间的归属/包含关系",核心字段: | 字段 | 含义 | |------|------| | `group_subject_id` | 父主体(`auth_subject.id`) | | `member_type` / `member_id` | 成员类型(1用户2科室3安全组4院区6角色8医疗组) 和成员主体(`auth_subject.id`) | | `is_direct` | 1直接成员 / 0继承冗余(展开后冗余落库的优化位) | | `effective_time` / `expire_time` | 成员生效/失效时间窗 | | `org_id` | 机构隔离(多院区/多机构) | `auth_subject` 是"授权主体"抽象层,注册表里定义了 8 类:`user/sys_user`、`dept/sys_dept`、`group/安全组`、`campus/院区`、`org/机构`、`role/sys_role`、`post/岗位`、`medical_group/医疗组`。 ## 为什么不能直接用 `sys_user` 你的 `SnapshotBuilder`(权限生效引擎)的逻辑证明了这一点——授权(`auth_grant`)是**授给"主体"**的,而不是直接授给人。它要做"三跳展开":grant → 主体 →(递归沿 `auth_subject_member`)→ 用户 → 能力。如果砍掉 `auth_subject_member`、直接用 `sys_user`,会立刻丢掉下面这些能力: 1. **按组/角色授权并自动级联到人**:给"心内科科室"或"某安全组"授一个权限,要能自动覆盖组内所有医生。只有 `sys_user` 的话,只能一个人一个人授,没有层级。 2. **递归嵌套的成员树**:科室包含角色、角色包含人、医疗组包含人和其他组。`auth_subject_member` 用 `group→member` 边 + 递归展开(带环检测、深度上限 16)来表达这种多叉层级,这是 `sys_user` 单表做不到的。 3. **与身份表解耦、可扩展**:`sys_user` 是账号/凭证/登录档案的存储;授权层用独立的"subject"抽象后,新增一种主体类型(岗位、医疗组…)只需往 `auth_subject_type` 注册表插一行,**Java 和建表语句都不用改**(引擎靠注册表判断 `type_key=user`,不写死 `==1`)。 4. **成员级时间窗**:某医生临时借调到某安全组 3 个月、到期自动退出——这种"按成员关系维度"的生效/失效,只能落在 `auth_subject_member` 上。 5. **多机构隔离**:`org_id` 让同一套授权模型在多个院区/机构下复用。 ## 结论 - 它可以"不用"——**前提是你的需求仅仅是"把权限直接授给单个用户"**。那样确实能退化成 `auth_grant.user_id` 直连 `sys_user`,省掉 subject 抽象。 - 但你们这个 `his_auth` 明显是按 **RBAC + 组织层级 + 多院区 + 时间窗** 设计的医疗权限系统,所以 `auth_subject_member` 是必要的:它是"组/角色/科室 → 人"的递归展开边表。删掉它,等于放弃按组织维度批量授权这一整个能力。 简单一句话:**`sys_user` 存的是"谁",`auth_subject`+`auth_subject_member` 解决的是"把权限授给谁(可能是人,也可能是科室/角色/组),并递归展开到人"**。两者职责不同,不能互相替代。 需要的话我可以帮你拉一下这三张表的实际数据量(subject / member 行数、各 member_type 分布),确认它在你们库里是不是真的在用组/角色授权,还是只退化成了"用户—用户"的关系。
↗ 分享

全部回复(0)

登录 后发表评论
还没有回复,来说两句~
相关推荐