实施服务器rbac的关键是厘清“谁能在哪组服务器上做什么”,核心在于模型设计、权限校验链路和分组语义落地,角色为权限容器而非命名标签,权限格式统一为资源:操作,校验依赖缓存化的扁平数组与三级链路(user→role→group_permissions),分组是刚性权限边界,敏感操作需双重校验,管理后台须支持角色-分组-权限动态授权。

实施服务器 RBAC,关键不是堆功能,而是理清“谁能在哪组服务器上做什么”。它不依赖语言或框架,核心是模型设计 + 权限校验链路 + 分组语义落地。
角色与权限要解耦,用资源:操作格式定义权限
角色不是“admin”“editor”这类名字,而是权限的容器。比如:
- 运维组管理员角色,配 server:reboot、server:install-package、alert:ack
- 只读监控员角色,只配 server:read、metric:list、alert:view
权限码统一用 资源:操作 格式(如 group:edit、server:delete),避免硬编码角色名判断。系统提供统一入口方法(如 can($permission)),内部只查缓存,不查库、不 JOIN。
服务器分组必须参与权限判定,不能只看角色
分组不是 UI 分类,而是权限边界。用户拥有某个角色,不等于自动获得所有服务器权限。必须明确:该角色在哪个分组内拥有哪些操作权限。
- 例如:用户 A 是“数据库组成员”,但仅当该角色在 DB-PROD 分组中被授予 server:read 和 alert:view,才可在该组服务器上执行对应操作
- 敏感操作(告警确认、重启、批量命令)必须双重校验:角色允许该操作 且 目标服务器属于用户被授权的分组
- 推荐用 ServerGroupServer 关联表建立“服务器↔分组”多对多关系,再走 user→role→group_permissions 三级链路校验
权限数据必须缓存,带版本控制防 stale
每次请求都查库查关联表,性能差还易出错。正确做法是登录后一次性加载并缓存:
- 缓存 key 建议为 "user_perms_{$uid}_v3",其中 v3 是版本号;角色或分组权限变更时,主动删除对应 key
- 缓存内容是扁平数组,如 ["server:read", "group:edit", "alert:ack"],校验时直接 in_array('server:reboot', $perms)
- 优先用 Redis(支持 TTL、跨实例共享、原子删);若用 session,务必确保中间件已执行 Auth::setUser($uid),否则权限永远为空
- 禁止把权限塞进 JWT payload(过长)、也禁用 JSON 字段存权限列表(无法索引、难校验、易 stale)
管理后台要支持动态分组授权
权限系统活不起来,往往因为后台只能增删角色,却不能指定“这个角色在那个分组里能干啥”。后台至少需提供三类页面:
- 角色管理:增删改权限码(如添加 server:backup)
- 分组管理:增删服务器(如将 10.0.1.10–10.0.1.15 加入 APP-STAGING)
- 角色-分组-权限授权页:选角色 + 选分组 + 勾选允许的操作(如给 “备份专员” 角色在 APP-STAGING 组中勾选 server:backup 和 server:status)











