简介
本技术文档围绕后台管理员的权限检查系统进行系统化说明,覆盖 RBAC 模型实现、角色与资源映射、URL/API/功能级权限控制、细粒度授权(数据/操作/时间)、权限缓存与更新、动态权限管理、以及权限审计与排障方法。重点聚焦于后台模块访问鉴权链路:认证中间件 → 权限中间件 → 授权门控服务 → 菜单/动作白名单 → 业务控制器。
项目结构
权限相关代码主要分布在以下位置:
- 后台认证与权限中间件:admin/middleware
- 授权判定与服务:admin/service/authorization、admin/service/menu、admin/service/manager
- 多 Guard 认证管理器:core/foundation/auth
- 前台会员认证门面:front/facade/Auth
- 小程序端工作台权限校验:miniprogram/*/services/permission.ts
- 历史 RBAC 工具参考:plugin/alipay/sdk/.../Rbac.php
graph TB
A["请求进入"] --> B["AuthMiddleware<br/>恢复登录态"]
B --> C["PermissionMiddleware<br/>解析路由模块/动作"]
C --> D["AdminGate<br/>canAccess() 判定"]
D --> E{"是否允许?"}
E -- 否 --> F["重定向到后台首页/登录页"]
E -- 是 --> G["继续执行控制器"]
核心组件
- 认证中间件 AuthMiddleware:负责从会话恢复管理员身份,未登录则跳转登录页。
- 权限中间件 PermissionMiddleware:在身份注入后,读取当前路由 module/action/targetId,调用 AdminGate 进行访问判定。
- 授权门控 AdminGate:承载「当前管理员能否访问指定模块/动作」的核心逻辑,支持超级管理员放行、子资源别名归一化、manager 自编辑特例。
- 菜单服务 AdminMenuService:提供基础菜单键列表,用于权限勾选与菜单渲染口径一致。
- 管理员服务 ManagerService:维护管理员账号、action_list 权限集合、操作日志查询与展示。
- 认证管理器 AuthManager:统一注册 admin/front/api 三端 Guard,保证 auth('xxx') 可解析。
- 前台认证门面 Auth:前台会员认证入口,提供 id/user/check 等能力。
- 小程序权限校验:work 模块前端通过后端接口校验权限,失败降级回首页。
- 历史 RBAC 工具:演示 allow/deny 优先级与资源路径匹配规则,供理解 ACL 思想参考。
架构总览
后台权限链路由中间件驱动,职责清晰分离:
- 认证层:AuthMiddleware 仅负责身份恢复与拦截。
- 授权层:PermissionMiddleware + AdminGate 组合完成模块/动作级访问控制。
- 数据层:ManagerService 维护管理员与 action_list,并输出菜单选项与日志视图数据。
- 门面层:AuthManager 统一暴露 auth('admin'|'front'|'api') 能力;前台使用 front facade。
sequenceDiagram
participant Client as "客户端"
participant AMW as "AuthMiddleware"
participant PMW as "PermissionMiddleware"
participant Gate as "AdminGate"
participant Ctrl as "控制器"
Client->>AMW : 请求后台页面
AMW->>AMW : restoreFromSession()
AMW-->>Client : 未登录则跳转登录页
AMW-->>PMW : 已登录则放行
PMW->>PMW : 解析 routeModule/routeAction/id
PMW->>Gate : canAccess(admin, cur, action, targetId)
Gate-->>PMW : true/false
PMW-->>Client : false 则重定向到后台首页
PMW-->>Ctrl : true 则继续处理
详细组件分析
后台认证中间件(AuthMiddleware)
- 职责:从会话恢复管理员信息,未登录直接抛出响应异常并重定向至登录页。
- 关键点:免登入口由路由声明式豁免,不在中间件内硬编码白名单。
权限中间件(PermissionMiddleware)
- 职责:在身份注入完成后,提取当前模块、动作与目标 ID,调用 AdminGate 判定。
- 关键点:空模块或无权限时重定向到后台首页;目标 ID 由 Request 显式传入,避免内部耦合。
授权门控(AdminGate)
- 核心逻辑:
- 超级管理员(type 非 defined)直接放行。
- 对 defined 类型管理员,按 action_list 白名单判定。
- 子资源 module 经别名表归一到父模块再查,确保父子继承透明。
- manager 模块的 edit/update 针对本人自编辑放行。
- 复杂度:O(n) 字符串分割与 in_array 查找,n 为 action_list 项数,通常较小。
flowchart TD
S["开始"] --> T{"是否超级管理员?"}
T -- 是 --> A["允许访问"]
T -- 否 --> M{"是否有模块名?"}
M -- 否 --> D["拒绝访问"]
M -- 是 --> E{"是否 manager 自编辑?"}
E -- 是 --> A
E -- 否 --> N["归一化模块名子→父"]
N --> L["解析 action_list"]
L --> C{"cur 是否在 action_list?"}
C -- 是 --> A
C -- 否 --> D
菜单服务(AdminMenuService)
- 职责:提供框架基础菜单键列表,用于权限勾选与菜单渲染口径一致。
- 作用:与 ManagerService 的 moduleOptions/adminActionList 共同决定“可见且可选”的权限项。
管理员服务(ManagerService)
- 职责:管理员账号增删改、action_list 权限集合维护、操作日志查询与展示。
- 关键点:
- insert/update/delete 中强校验当前管理员权限(ALL 或本人)。
- buildManagerLogData 对非 ALL 管理员强制锁定自身范围,防止越权。
- moduleOptions/adminActionList 产出权限勾选候选,口径与菜单一致。
认证管理器(AuthManager)
- 职责:统一注册 admin/front/api 三端 Guard,保证 auth('xxx') 始终可解析。
- 设计要点:无默认 Guard,必须显式传名;user 模块可选安装时以 GuestGuard 兜底。
前台认证门面(Auth)
- 职责:前台会员认证入口,提供 id/user/check 等方法,配合 Init 期注册。
- 注意:业务属性(VIP/工作端/分销)由 UserService 承担,本类不暴露这些方法。
小程序工作台权限校验
- 行为:前端尝试获取 work.permission 路由地址,若不存在或后端校验失败,则 switchTab 回首页。
- 目的:跨模块共用统一的工作台权限入口,简化前端判断。
历史 RBAC 工具(参考)
- 行为:checkAcl 支持 allow/deny 优先级与资源路径通配匹配。
- 用途:帮助理解 ACL 思想与资源层级匹配策略,便于扩展细粒度控制。
依赖关系分析
- 中间件依赖:
- PermissionMiddleware 依赖 AdminGate。
- AuthMiddleware 依赖 session 恢复能力。
- 服务依赖:
- ManagerService 依赖 AdminMenuService 与数据库模型。
- AdminGate 依赖静态别名表与管理员上下文。
- 门面依赖:
- AuthManager 聚合各端 Guard 工厂。
- 前台 Auth 门面依赖用户服务(按需懒加载)。
classDiagram
class AuthMiddleware {
+handle(next) mixed
}
class PermissionMiddleware {
+handle(next) mixed
}
class AdminGate {
+canAccess(admin, cur, action, targetId) bool
+isManagerSelfEdit(admin, cur, action, targetId) bool
}
class AdminMenuService {
+basicMenu() array
}
class ManagerService {
+insert(data) int
+update(data) void
+delete(id, post) array
+moduleOptions() array
+adminActionList(admin_id) array
}
class AuthManager {
+guard(name) object
}
class FrontAuth {
+id() int
+user() array
+check() bool
}
PermissionMiddleware --> AdminGate : "调用"
ManagerService --> AdminMenuService : "依赖"
AuthManager --> FrontAuth : "注册/解析"
AuthMiddleware --> PermissionMiddleware : "管道顺序"
性能与缓存策略
- 当前实现特点:
- 权限判定走内存中的 action_list 字符串分割与数组匹配,开销小。
- 子资源别名表为静态数组,命中即归一化,无额外 I/O。
- 建议优化:
- 将 action_list 预编译为哈希集合(如关联数组),将 in_array 降为 O(1)。
- 对频繁读用的菜单选项(moduleOptions/basicMenu)做进程级缓存,减少重复计算。
- 在管理员权限变更时触发缓存失效,保证一致性。
配置与动态权限管理
- 权限来源:
- 管理员 action_list 字段存储模块白名单(逗号分隔)。
- 菜单候选来自配置与基础菜单键列表,保证 UI 与判定口径一致。
- 动态调整:
- 通过管理员编辑界面修改 action_list,立即影响后续请求的 canAccess 判定。
- 新增子资源需在 AdminGate 的别名表中登记,否则父模块授权无法透传到子资源。
- 安全边界:
- 非 ALL 管理员不可越权查看他人日志或修改他人资料。
- manager 自编辑仅限本人 ID 匹配。
细粒度授权机制
- URL 级别:
- 通过 PermissionMiddleware 解析 routeModule/routeAction,结合 AdminGate 判定模块/动作访问。
- API 级别:
- 当前仓库未发现统一的 API 级权限中间件;如需扩展,可在 API 路由前增加鉴权中间件,复用 AdminGate 或引入基于角色的 ACL 判定。
- 功能级别:
- 通过 action_list 控制模块级功能开关;更细粒度可按动作拆分(例如 index/show/edit/delete),在 AdminGate 中扩展 action 匹配。
- 数据级别:
- 日志查询强制按管理员范围过滤,防止越权读取。
- 可扩展:在 Service 层按数据归属(如企业/团队/部门)附加 where 条件。
- 操作级别:
- 关键写操作(删除/更新)采用二次确认与 DomainException 阻断,记录审计日志。
- 时间级别:
- 当前未见时间维度权限控制;可通过策略服务在 canAccess 中叠加时间窗口判定(如仅工作日/时段开放)。
权限审计与日志
- 审计写入:
- 管理员增删改、分类删除等操作均调用审计服务记录 action/module/details/ip 等信息。
- 日志查询:
- buildManagerLogData 支持按管理员、动作、模块、IP、日期范围筛选,并对非 ALL 管理员强制锁定自身范围。
- 日志展示:
- renderAdminLogRow 将原始行转换为模板可读结构,包含模块/动作中文标签与结果文本。
测试、调试与常见问题
- 测试建议:
- 构造不同 type 的管理员(超级管理员 vs defined),验证 canAccess 分支。
- 新增子资源后,验证父模块授权是否能透传到子资源(需登记别名)。
- 模拟 manager 自编辑场景,验证 targetId 与当前 admin_id 匹配逻辑。
- 对日志查询,构造非 ALL 管理员,验证其只能看到自身日志。
- 调试方法:
- 在 PermissionMiddleware 中打印 routeModule/routeAction/id,确认路由解析正确。
- 在 AdminGate::canAccess 中打印 action_list 与 cur,定位匹配失败原因。
- 检查 ManagerService::moduleOptions 与 basicMenu 是否包含期望模块。
- 常见问题:
- 子资源无法访问:未在 AdminGate 别名表中登记父模块映射。
- 定义型管理员误判:action_list 为空或未包含目标模块。
- 自编辑被拒:targetId 未正确传入或当前 admin_id 无效。
- 日志越权:非 ALL 管理员仍能看到他人日志(应检查构建查询时的强制锁定逻辑)。
结论
该权限系统以中间件为核心,将认证与授权解耦,并通过 AdminGate 集中实现模块/动作级访问控制。配合 ManagerService 的权限集合管理与审计日志,形成闭环。建议在现有基础上进一步:
- 将 action_list 匹配优化为 O(1) 哈希集合。
- 扩展 API 级权限中间件与功能级动作控制。
- 引入数据与时间维度的细粒度策略服务。
- 完善权限变更后的缓存失效与一致性保障。