RBAC / 权限 总览待审核
Server · 分层拦截

Server 层:从 Middleware 到 Repository 的逐层拦截

安全校验的最终位置在后端(UI 层的显隐只是体验)。一个请求穿过一条流水线,每一层管一件事: Middleware 认身份和角色 → Router 声明这个 API 要什么 capability → Controller 只编排、不判权 → Service 带上业务上下文 → Domain 执行业务规则 → Repositoryscope 过滤数据。 选一个场景,逐层单步执行,看请求在哪一层放行、在哪一层被拦截。

选好场景,点「下一步」。

can / assert / scope 三个原语

API问的问题用在哪
can(key)有没有这条能力?返回 booleanUI 显隐、分支判断
assert(key)没有就抛 403,有就继续Router / Service 守卫,拦截无权限的请求
scope(key)这条能力的数据范围是什么 (Full/Group/Self)?Repository 拼 WHERE 条件
ScopeResolver:scope(key) 得到的范围,翻译成具体的查询约束 —— 输入 (capability, 当前用户),输出 { where, 或 拒绝 }。 它是「对谁做」在数据层的落地点:Self → WHERE owner_id = meGroup → WHERE group_id = me.groupFull → 无约束 对象级授权(object-level)必须下沉到数据层。Router 的 assert(order:cancel) 只回答「这个用户一般能不能取消订单」;但「能不能取消这一张订单(它是不是在我的 scope 里)」 要等真的取到这条记录才知道。所以 scope 过滤放在 Repository—— 要么进 WHERE(查不到=不存在),要么取出后断言 owner === me。 只在 Router 拦截,等于只做了「类级」授权,会遗漏「越权访问他人某一条记录」的情况。 分层各司其职,职责不互相渗透: Controller 只做编排、不写权限判断;业务规则(「done 的单不能取消」)属于 Domain,不要放进 Controller 或 SQL;Repository 只负责 scope 过滤,不涉及业务。 职责划分清楚,权限逻辑才便于排查、便于测试。