rbac核心是“谁能在哪组服务器上做什么”,需通过角色-分组-权限三级链路校验,权限码用资源:操作格式,缓存扁平数组并带版本控制,管理后台须支持动态分组授权。

实现服务器 RBAC(基于角色的访问控制),关键不是堆功能,而是理清“谁能在哪组服务器上做什么”。它不依赖特定语言或框架,核心是模型设计 + 权限校验链路 + 分组语义落地。下面从实际可操作的角度说清楚。
明确角色与权限的绑定逻辑
角色不是“admin”“editor”这种名字,而是权限的容器。比如:
- 一个 运维组管理员 角色,应关联权限如
server:reboot、server:install-package、alert:ack - 一个 只读监控员 角色,只配
server:read、metric:list、alert:view - 权限码建议用
资源:操作格式(如group:edit、server:delete),避免硬编码角色名判断 - 系统中必须有统一入口(如
can($permission)方法),内部只查缓存数组,不查库、不 JOIN
服务器分组必须参与权限判定
RBAC 在服务器监控场景中,分组不是 UI 分类,而是权限边界。不能只靠角色决定“能操作”,还要看“能操作哪几台”:
- 用户 A 是“数据库组成员”,但该角色本身不自动获得所有服务器权限;需额外配置:该角色在 DB-PROD 组 内拥有
server:read和alert:view - Nezha Monitoring 的做法值得参考:用
ServerGroupServer关联表建立“服务器↔分组”多对多关系,再通过user→role→group_permissions三级链路做最终校验 - 告警、重启、批量命令等敏感操作,必须同时校验:用户角色是否允许该操作 + 目标服务器是否属于该用户被授权的分组
权限数据要缓存且带版本控制
每次接口请求都查库查关联表,性能差还容易出错。正确做法是登录后一次性加载并缓存:
- 缓存 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)
管理后台要支持动态分配与验证
权限系统活不起来,往往因为后台只能增删角色,却不能指定“这个角色在那个分组里能干啥”:
- 后台至少提供三类页面:角色管理(增删改权限码)、分组管理(增删服务器)、角色-分组-权限 授权页(选角色 + 选分组 + 勾选允许的操作)
- 数据库最小结构仍是 4 张表:
users、roles、permissions、role_permissions;若需分组级授权,再加role_group_permissions表 - 每个授权操作都要落日志,包括谁、什么时候、给哪个角色在哪个分组下添加了哪些权限——这是审计和排障的基础











