试用安装包下载 | SMS | 在线演示项目源码地址https://github.com/openskeye/go-vss本文将详细描述 Skeyevss 管理端与业务前台在工程中的权限定义方式、组织与角色如何落库、一次 HTTP 请求如何从登录态推导权限并最终校验接口并说明前端如何消费权限元数据。内容以当前仓库实现为准。1. 设计目标目标实现要点前后台分域权限资源在代码中分为backendP_0*与frontendP_1*两棵逻辑树统一由permissions.Source()暴露给前端做菜单/按钮控制。RBAC管理员隶属于组织部门部门挂载角色角色持有权限点 ID 列表permissionUniqueIds。超级管理员旁路管理员Super 1时中间件不拼接业务权限列表接口校验阶段直接放行见下文。高性能读路径全量「管理员 部门 角色」通过 DB RPCAuthRes拉取后在 Backend API 进程内缓存变更后通过AuthSet等 channel 节流刷新参考 《数据查询优化》。接口级强校验除登录、鉴权通路的通用中间件外各 Handler 对具体操作显式调用permissions.Verify.Authentication与前端展示的权限 ID 同源代码常量避免「前端藏菜单、接口仍可用」的脱节。2. 核心概念与数据模型2.1 实体关系逻辑depIdsroleIdspermissionUniqueIds管理员 Admin部门 Department角色 Role权限点 P_*权限点元数据以源码树为准UniqueId、Universal、Super等字段见permissions.Item。管理员Admin字段含Super、DepIdsJSON 存库业务层展开为[]uint64。非超级管理员若DepIds为空中间件直接拒绝localization.M0011。部门DepartmentState 1且 ID 落在管理员DepIds中的部门参与权限计算部门上RoleIds汇总为候选角色。角色RoleState 1且 ID 被上述部门引用时生效PermissionUniqueIds为权限点字符串列表与代码中定义的P_*一一对应。权限点Permission Node不单独建「权限表」作为主数据以 Go 源码树为权威定义运行时init()注册到内存maps供校验与下发前端。2.2 权限资源定义代码即协议包路径core/common/source/permissions/结构Item包含UniqueId、Name、Universal、Super、ActionType、子节点Children等。权限树backendP_0名称「后台权限」、frontendP_1名称「前台权限」。对外聚合permissions.Source()返回map[string][]*Item键为backend/frontend值为各自一级子节点列表供「系统设置」类接口下发完整树供前端渲染菜单与按钮。权限 ID 在backend.go、frontend.go中以常量声明如P_0_1_2_1角色创建新增菜单或接口时必须同步增加常量并在树中挂好同时在对应 Handler 里写入Authentication(..., permissions.P_xxx, ...)。3. 运行时数据AuthRes与中间件3.1 全量权限相关快照类型定义于core/common/types/auth.goAdmins、Departments、Roles均为列表由 DB 服务BackendService.AuthRes一次查出并序列化返回Backend API 侧缓存在进程内供每个请求推导当前用户权限无需每请求扫库。3.2 从 JWT 到「当前用户权限 ID 列表」context内存 AuthRes 快照Token 解析BaseMiddleware AuthMiddleware客户端context内存 AuthRes 快照Token 解析BaseMiddleware AuthMiddleware客户端alt[Admin.Super 1][普通管理员]Authorization 业务头校验 token写入 userid按 userid 查找 AdminSUPER、DEP_IDS、PERMISSION_IDSnil 等根据 DepIds 过滤 State1 的 Department收集 Department.RoleIds合并 State1 的 Role.PermissionUniqueIdsDEP_IDS、SUPER、PERMISSION_IDS中间件将结果写入context键名见core/constants/header.goCTX_SUPER_STATE是否超级管理员uint。CTX_DEP_IDS当前用户部门 ID 列表。CTX_PERMISSION_IDS当前用户展平后的权限点 ID 列表超级管理员场景下校验函数不依赖此列表。实现见core/app/sev/backend/internal/middleware/authmiddleware.go中permissions()与CustomerCall。3.3 接口级校验Verify.Authentication各业务 Handler 在鉴权通过后调用permissions.New(ctx).Authentication(contextx.GetSuperState(ctx),permissions.P_0_x_x_x,// 本接口对应的权限点 IDcontextx.GetPermissionIds(ctx),// 中间件注入的展平列表)规则摘要core/common/source/permissions/verify.go条件结果权限 ID 未在init注册的maps中权限未配置开发期配置错误super 0直接通过该节点Universal true直接通过如「获取设置」类只要求登录用户权限列表不包含该uniqueId无权限[001]该节点Super true且当前非超管无权限[002]预留字段树中可按需标记说明超级管理员在中间件阶段已标记Authentication内对super 0短路普通用户必须持有显式permissionUniqueId或由角色的权限列表覆盖到该点。4. 前端权限模型与后端对齐前端不单独维护一套 ID 规则而是依赖接口返回Permissionspermissions.Source()的 JSON含backend/frontend完整树用于侧栏、路由元信息、按钮显隐。PermissionIds当前登录用户已拥有的权限点 ID 列表与中间件注入一致用于快速includes判断。Super/Showcase超级管理员与演示账号等展示策略见SettingLogic与中间件中的CTX_SHOWCASE。下发入口在core/app/sev/backend/internal/logic/config/setting/settinglogic.go的Setting()返回值common.Setting结构体字段Permissions、PermissionIds、Super、Showcase等。Web 前端Backend APIpermissions.Source()完整权限树contextx.GetPermissionIds当前用户 ID 列表Setting 接口聚合菜单 / 路由按钮级重要前端隐藏仅改善体验真正的安全边界在 Handler 的Authentication。新增页面时须同时改权限树、角色可选项与后端 Handler 校验常量。5. 与「内部调用 / 设备操作员」相关的约定后台权限树中包含「内部调用」等子树如P_0_7_*对应转发 VSS、流媒体、云台等业务 API同样走Authentication。permissions.EquipmentOperator()在代码中汇总了一组前后台权限 ID 字符串便于初始化「设备操作员」类角色时批量勾选实现见main.go。6. 配置变更如何生效当管理员、角色、部门等影响AuthRes的数据被修改时对应 Logic 在写库成功后会向ServiceContext.AuthSet发送通知监听协程经ThrottleFixedGridTrailing合并后调用fetchAuth()刷新内存中的authRes。因此权限变更后已签发 JWT的旧连接仍携带旧userid但下一次请求会使用刷新后的 AuthRes重算PermissionIds一般可在短时间内生效而无需重新登录除非业务另有 token 版本策略。7. 扩展与维护新增权限点在backend.go或frontend.go增加常量 → 挂到Item树 → 确保initVerifyData后 ID 全局唯一重复会在init时log.Fatalf。新增 API在对应*handler.go增加Authentication(..., permissions.P_new, ...)。新增角色默认能力可考虑扩展EquipmentOperator()或提供迁移 SQL/种子数据为角色写入新的permission_unique_ids。部门/角色停用依赖State字段过滤避免下线部门/角色仍参与权限并集。8. 总结定义前后台权限是代码内的树形资源P_0*/P_1*为稳定协议角色存ID 列表与之绑定。推导AuthRes 管理员部门 部门角色 → 展平permissionUniqueIds写入上下文。校验超级管理员旁路Universal登录即可其余接口显式校验常量 ID。前端同一套树 当前用户 ID 列表驱动 UI与后端 Handler 成对使用。