加载中…
文档目录
角色管理

简介

本文件面向 DouPHP 后台“角色管理”能力,围绕 RBAC(基于角色的访问控制)在系统中的落地进行系统化说明。重点覆盖:

  • 角色定义与层次化设计:通过管理员类型与权限集合实现“超级管理员/普通管理员/自定义权限管理员”的层级划分。
  • 基础操作:角色创建、修改、删除等流程与校验。
  • 权限继承机制:子模块对父模块的鉴权透明继承策略。
  • 角色分组与复制:以“动作列表”为粒度进行权限组合与复用。
  • 数据模型与权限树:管理员表字段、权限集合与菜单/模块来源。
  • 界面与交互:新增/编辑/删除页面、权限勾选、日志审计。
  • API 与前端流程:控制器路由到服务层的调用链、表单校验与响应。
  • 审计与变更追踪:操作日志记录、过滤与展示。

项目结构

角色管理相关代码主要分布在以下位置:

  • 控制器层:负责请求处理、视图渲染与跳转。
  • 服务层:封装业务规则、权限判定、数据组装与审计写入。
  • 模型层:持久化管理员账号与操作日志。
  • 中间件层:身份注入与权限拦截。
  • 配置层:模块清单、隐藏项、系统开关等影响权限范围。
graph TB
subgraph "控制器"
MC["ManagerController"]
end
subgraph "服务"
MS["ManagerService"]
AM["AdminGate"]
end
subgraph "模型"
Mgr["Manager"]
Log["ManagerAdminLog"]
end
subgraph "中间件"
AuthMW["AuthMiddleware"]
PermMW["PermissionMiddleware"]
end
subgraph "配置"
CfgMod["module.php"]
CfgSys["system.php"]
CfgApp["config.php"]
end
MC --> MS
MS --> Mgr
MS --> Log
PermMW --> AM
AuthMW --> MC
MS --> CfgMod
MS --> CfgSys
MS --> CfgApp

核心组件

  • 管理员控制器(ManagerController)
    • 提供列表、新增、编辑、删除、日志等页面入口。
    • 仅允许拥有全部权限的管理员创建新管理员;编辑时限制只能编辑本人或具备全部权限者。
  • 管理服务(ManagerService)
    • 封装新增/更新/删除逻辑、列表与编辑数据构建、权限选项生成、日志查询与渲染。
    • 维护“动作列表”的存储格式(逗号分隔),并支持“自定义权限”模式。
  • 授权门控(AdminGate)
    • 判断当前登录管理员是否可访问指定后台模块/动作。
    • 支持子模块对父模块的鉴权别名映射,实现透明继承。
  • 管理员模型(Manager)
    • 定义 admin 表的填充字段与常用查询方法。
  • 中间件(AuthMiddleware、PermissionMiddleware)
    • 完成身份注入与权限拦截,将管理员上下文传递给后续控制器与服务。

架构总览

下图展示了从请求进入、身份认证、权限判定到控制器/服务处理的完整链路,以及权限选项与菜单来源。

sequenceDiagram
participant Client as "浏览器"
participant AuthMW as "身份中间件"
participant PermMW as "权限中间件"
participant Ctrl as "管理员控制器"
participant Svc as "管理服务"
participant Gate as "授权门控"
participant DB as "数据库"
Client->>AuthMW : 发起后台请求
AuthMW-->>Client : 未登录则重定向登录
AuthMW->>PermMW : 已登录,传递管理员上下文
PermMW->>Gate : 判定是否可访问当前模块/动作
alt 允许访问
PermMW-->>Ctrl : 放行
Ctrl->>Svc : 执行业务增删改查/日志
Svc->>DB : 读写管理员与日志
Svc-->>Ctrl : 返回结果
Ctrl-->>Client : 渲染页面/跳转
else 拒绝访问
PermMW-->>Client : 返回无权限提示
end

详细组件分析

角色数据模型与权限集合

  • 管理员表关键字段
    • 用户名、邮箱、密码哈希、动作列表(action_list)、创建时间、最后登录时间与 IP、失败次数与锁定时间、令牌等。
  • 动作列表(action_list)
    • 存储形式为逗号分隔的模块/动作短名集合。
    • 特殊值:ALL(超级管理员)、ADMIN(平台管理员)、DEFINED(自定义权限)。
  • 权限来源
    • 列式模块(column_module)、单页模块(single_module)、基础菜单(basicMenu)共同构成可选权限项。
    • 可通过配置隐藏部分模块或功能。
erDiagram
ADMIN {
int id PK
string username UK
string email
string password
string action_list
datetime created_at
int last_login
string last_ip
int login_fail_count
datetime login_locked_at
string token
datetime token_expires_at
string reset_token
datetime reset_token_expires_at
}

角色创建、修改、删除流程

  • 创建角色
    • 仅 ALL 权限管理员可创建。
    • 支持三种类型:ALL、ADMIN、DEFINED(自定义权限需至少选择一个模块)。
    • 密码采用安全哈希存储。
    • 成功后写入审计日志。
  • 修改角色
    • ALL 权限者可编辑任意管理员;非 ALL 权限者仅能编辑自身。
    • 修改密码需验证旧密码(兼容历史 MD5 与 bcrypt)。
    • 可更新用户名、邮箱、动作列表。
    • 成功后写入审计日志。
  • 删除角色
    • 仅 ALL 权限管理员可删除。
    • 禁止删除自己。
    • 二次确认后执行删除,并写入审计日志。
flowchart TD
Start(["开始"]) --> CheckAll{"是否ALL权限?"}
CheckAll --> |否| Deny["拒绝: 无权限"]
CheckAll --> |是| Mode{"操作类型"}
Mode --> |创建| Create["校验输入/选择权限/哈希密码/插入记录/写日志"]
Mode --> |更新| Update["校验输入/验证旧密码(如需)/更新字段/写日志"]
Mode --> |删除| Delete["校验目标/禁止自删/二次确认/删除记录/写日志"]
Create --> End(["结束"])
Update --> End
Delete --> End
Deny --> End

权限继承与子模块映射

  • 子资源模块(如 AI 任务、AI 日志、微信媒体文章等)在鉴权时透明继承其父模块。
  • 当管理员勾选了父模块权限后,对应子资源自动获得访问能力,无需重复配置。
  • 新增子资源需在别名表中登记,否则即使父模块已授权也可能被拦截。
flowchart TD
A["当前模块名"] --> B{"是否在子模块别名表?"}
B --> |是| C["映射为父模块名"]
B --> |否| D["保持原模块名"]
C --> E["读取管理员动作列表"]
D --> E
E --> F{"父/原模块是否在动作列表中?"}
F --> |是| G["允许访问"]
F --> |否| H["拒绝访问"]

角色分组管理与角色复制

  • 角色分组
    • 通过“动作列表”的组合形成不同角色分组(ALL、ADMIN、DEFINED)。
    • 自定义权限(DEFINED)可按需勾选模块,形成细粒度分组。
  • 角色复制
    • 通过复制现有管理员的动作列表,快速创建具有相同权限的新角色。
    • 可在新增/编辑时直接沿用已有 action_list 作为模板。

权限树结构与菜单控制

  • 权限树来源
    • 列式模块(含分类与主表)、单页模块、基础菜单(模块、小程序、主题等)。
    • 通过配置项排除隐藏模块,保证权限树与实际可见菜单一致。
  • 菜单控制
    • 权限中间件依据管理员动作列表决定可访问模块。
    • 控制器侧根据权限决定是否渲染“创建”等操作按钮。
graph LR
ModCfg["模块配置<br/>column_module/single_module"] --> Tree["权限树"]
BasicMenu["基础菜单<br/>basicMenu"] --> Tree
HideCfg["隐藏配置<br/>no_show_menu/admin_hidden_single"] --> Tree
Tree --> UI["后台菜单/按钮显示"]
Tree --> Gate["权限判定"]

动态权限检查与菜单控制逻辑

  • 动态检查
    • 每次请求经权限中间件调用授权门控,结合管理员上下文判定是否放行。
    • 针对 manager 模块的“编辑自身资料”单独放行,便于管理员自助维护。
  • 菜单控制
    • 控制器根据当前管理员的 action_list 决定是否渲染“创建”等入口。
    • 列表与编辑页根据权限动态调整可用操作。
sequenceDiagram
participant MW as "权限中间件"
participant Gate as "授权门控"
participant Ctrl as "控制器"
MW->>Gate : canAccess(admin, module, action, targetId)
alt 允许
Gate-->>MW : true
MW-->>Ctrl : 继续处理
Ctrl->>Ctrl : 根据权限渲染按钮/入口
else 拒绝
Gate-->>MW : false
MW-->>MW : 返回无权限
end

角色管理的API接口设计与前端交互流程

  • 后端接口(路由到控制器)
    • 列表:GET /admin/manager
    • 新增:GET /admin/manager/create;POST /admin/manager
    • 编辑:GET /admin/manager/edit?id=...;POST /admin/manager/update
    • 删除:POST /admin/manager/destroy?id=...(二次确认)
    • 日志:GET /admin/manager/log
  • 前端交互
    • 列表页展示管理员信息、类型、最后登录时间。
    • 新增/编辑页提供权限勾选框,按模块/动作维度组织。
    • 删除前弹出二次确认,确认后执行删除。
    • 日志页支持按用户名、操作类型、模块、IP、日期范围筛选。
sequenceDiagram
participant FE as "前端页面"
participant Ctrl as "管理员控制器"
participant Svc as "管理服务"
participant DB as "数据库"
FE->>Ctrl : GET /admin/manager
Ctrl->>Svc : buildManagerListData()
Svc->>DB : 查询管理员列表
DB-->>Svc : 列表数据
Svc-->>Ctrl : 组装数据
Ctrl-->>FE : 渲染列表
FE->>Ctrl : POST /admin/manager (新增)
Ctrl->>Svc : insert(data)
Svc->>DB : 插入管理员
Svc-->>Ctrl : 返回新ID
Ctrl-->>FE : 重定向至编辑页
FE->>Ctrl : POST /admin/manager/destroy (删除)
Ctrl->>Svc : delete(id, post)
Svc->>DB : 删除管理员
Svc-->>Ctrl : 返回结果
Ctrl-->>FE : 提示成功/失败

角色权限审计与变更追踪

  • 审计写入点
    • 新增管理员:记录创建操作。
    • 更新管理员:记录更新操作(包含旧密码错误场景)。
    • 删除管理员:记录删除操作。
  • 日志查询
    • 支持按管理员账号、操作类型、模块、IP、起止日期筛选。
    • 非 ALL 权限管理员仅能查看自身日志,防止越权。
  • 日志渲染
    • 统一渲染行结构,包含模块、动作、结果、详情、IP、时间等。
flowchart TD
Op["管理员操作"] --> Audit["审计写入"]
Audit --> Store["写入admin_log"]
Store --> Query["日志查询/过滤"]
Query --> Render["渲染日志列表"]

依赖关系分析

  • 控制器依赖服务层进行业务处理与数据组装。
  • 服务层依赖模型进行数据持久化,依赖配置获取模块清单与系统开关。
  • 权限中间件依赖授权门控进行访问控制。
  • 审计日志贯穿增删改流程,确保可追溯性。
graph TB
Ctrl["ManagerController"] --> Svc["ManagerService"]
Svc --> ModelMgr["Manager"]
Svc --> ModelLog["ManagerAdminLog"]
PermMW["PermissionMiddleware"] --> Gate["AdminGate"]
Svc --> Cfg["配置(module/system/config)"]

性能考虑

  • 权限判定
    • 子模块到父模块的映射为常量数组,查找复杂度 O(1)。
    • 动作列表解析为字符串分割与 in_array 判断,整体复杂度与权限项数量线性相关。
  • 日志查询
    • 使用分页与条件过滤,避免全表扫描。
    • 非 ALL 权限管理员强制锁定查询范围,减少不必要的数据读取。
  • 缓存建议
    • 可将模块清单与基础菜单结果进行短期缓存,降低频繁配置读取开销。

故障排查指南

  • 无法访问某模块
    • 检查管理员类型是否为 defined,且动作列表是否包含该模块或其父模块。
    • 若为子模块,确认已在别名表中登记。
  • 创建/更新失败
    • 检查表单校验与必填项(如自定义权限至少选择一个模块)。
    • 更新密码时确认旧密码正确(兼容历史 MD5 与 bcrypt)。
  • 删除失败
    • 确认不是删除自己;二次确认是否提交。
  • 日志为空或受限
    • 非 ALL 权限管理员仅能看到自身日志;检查筛选条件是否过严。

结论

DouPHP 后台角色管理以“管理员 + 动作列表”为核心,实现了清晰的 RBAC 分层与灵活的权限组合。通过子模块到父模块的鉴权继承、严格的权限中间件拦截、完善的审计日志与可控的菜单展示,既保证了安全性,又提升了管理效率。建议在扩展新模块时同步更新权限树与别名映射,确保权限体系的一致性。

附录

  • 关键路径参考
    • 权限判定:AdminGate.php:29-91
    • 角色增删改:ManagerController.php:77-175、ManagerService.php:122-243
    • 权限选项与菜单:ManagerService.php:548-606
    • 日志审计:ManagerService.php:383-467、ManagerService.php:515-540
添加日期:2026-10-05