外观
RBAC 同步规范
迁移概览
Legacy 继续写 users、menu.qx 和 qx_list;Beta 不做双写,而是通过 lims:rbac-sync 将这些数据镜像到 rbac_* 表。Beta 的权限判断读取快照,Legacy 仍是权限变更的唯一写入入口。
text
Legacy users / menu.qx / qx_list
│ lims:rbac-sync
▼
rbac_permissions / rbac_roles / rbac_user_permission_snapshots / rbac_menu_permissions
│
▼
Beta 路由权限与菜单可见性改用户组、权限字段或菜单规则后,先完成 Legacy 更新,再执行:
bash
php artisan lims:rbac-sync
php artisan lims:rbac-verify如果同步结果与 Legacy 不一致,应先修正数据或同步逻辑;不要为临时恢复访问而放开生产环境的 RBAC。路由权限开关由 config/rbac.php 中的 RBAC_ENFORCE 控制。
命令
bash
cd beta
php artisan lims:rbac-sync [--fzx-id=] [--dry-run] [--report=path]
php artisan lims:rbac-verify [--sample-users=50] [--sample-menus=100]代码位置
beta/app/Services/Rbac/Sync/
PermissionCatalogSync.php # P1–P2
RoleSync.php # P3
UserRoleSync.php # P4
UserPermissionSnapshotSync.php # P5
MenuPermissionSync.php # P6
RbacSyncReport.php
beta/app/Services/Rbac/Legacy/
LegacyQxCatalogReader.php
LegacyMenuReader.php
LegacyUserReader.php
beta/app/Console/Commands/
RbacSyncCommand.php
RbacVerifyCommand.php读侧:app/Foundation/Permission/、Http/Middleware/PermissionMiddleware.php。
同步阶段
幂等 upsert,可重复跑。
| Phase | 输入 | 输出 |
|---|---|---|
| P0 | env / --fzx-id | rbac_sync_runs |
| P1 | qx_list tie=0/1 | permissions 父子节点 |
| P2 | 本现场 qx.php + SHOW COLUMNS users | permissions 补全 |
| P3 | users group='0' | roles + role_permissions |
| P4 | users group!='0' | user_roles |
| P5 | 非 admin 用户 | user_permission_snapshots |
| P6 | menu | menu_permissions |
sync 不调 update_users_qx_by_group(),只读当前 users 列值。改组后现场顺序:组校正 → rbac-sync → rbac-verify。
P2:权限目录与动态列
每个部署只有一份有效权限目录,不是把 gx_file/*_qx.php 全并进来。
| 来源 | 处理 |
|---|---|
qx_list(tie=1, qx 非空) | 主来源 |
本现场 user_manage/qx.php | include 一次;若现场用 gx_file/{dw}_qx.php 覆盖,以 include 结果为准;source=php_catalog |
SHOW COLUMNS FROM users | varchar(1) 且在 qx 白名单或 qx_list 里 |
目录缺失列(users 有列、目录无定义):仍建 permissions,name=code,is_active=0,is_catalog_missing=1;verify 报告列出,不删列;beta 不对其鉴权。
std_code:P1–P2 不写入,保持 NULL;仅 migration 建列,后期人工或 beta 管理页维护。
init_qx_list() 加了新列后跑 sync;报告里 new_permissions > 0 要留意。
verify 规则
| # | 项 | 通过标准 |
|---|---|---|
| VR1 | 权限覆盖 | active 且 qx 非空的 code 全在 permissions |
| VR2 | 组权限 | 每个 role 的 role_permissions 记录集合 = 组行值为 1 的权限列集合 |
| VR3 | 用户权限 | 抽样 N 个非 admin:user_permission_snapshots.has_permission = users.{qx} |
| VR3b | 组 union 审计 | same_as_role_permissions=0 写入报告(参考) |
| VR4 | 菜单 | 抽样 M 个 menu:算法 B = get_menu.php 主路径 |
| VR5 | admin | users.admin=1 → superuser |
VR4 第一版不覆盖:site_type 动态子项、shuju_tongji 分支、penetration_test()。
什么时候可以开鉴权
sync + verify 阶段(路由还不拦):
- migration 通过
- 连续两次 sync 无增量
- VR1–VR2 全过
- VR3:≥50 用户 0 不一致
- VR4:≥100 menu 不一致率 ≤1%
开 PermissionMiddleware:上面全过 + 单测 + RBAC_ENFORCE=true 试点 + 人工改组→sync→403/200。
开 MenuService 新规则:试点一周无 P0 + BETA_MENU_RBAC=true(可回滚)。
生产默认 enforce:改权限 SOP 含 sync;RBAC_FALLBACK_LEGACY_SESSION 必须 false。
以下情况先停:
- legacy 有权限、
user_permission_snapshots无行 - sync 后菜单可见项骤降 >5% 且无解释
- 生产 enforce 但 >24h 未 sync
上线前
bash
cd beta
php artisan migrate --path=database/migrations/2026_xx_xx_create_rbac_tables.php
php artisan lims:rbac-sync --dry-run
php artisan lims:rbac-sync
php artisan lims:rbac-verify --sample-users=20 --sample-menus=50
php artisan test --filter=Rbac人工:legacy 改组 → sync → beta 菜单对;无权限用户访问受保护路由 403。
常见坑:legacy 改权限 beta 滞后(改完跑 sync);menu token 解析错(用 BETA_MENU_RBAC 开关回滚);快照缺失会 silent deny(VR3 零容忍 + A4 日志)。