ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

cloudbase-extension-cms 权限体系实现原理:从源码角度理解资源级权限设计

cloudbase-extension-cms 权限体系实现原理:从源码角度理解资源级权限设计 cloudbase-extension-cms 权限体系实现原理从源码角度理解资源级权限设计【免费下载链接】cloudbase-extension-cms 一站式云端内容管理系统 - An open source Node.js headless cms based on CloudBase项目地址: https://gitcode.com/gh_mirrors/cl/cloudbase-extension-cms对于很多初次接触 cloudbase-extension-cms 的开发者来说最想搞清楚的问题之一就是它小而美的权限体系到底是怎么运转的。作为一个基于腾讯云 CloudBase 的开源 Node.js Headless CMScloudbase-extension-cms 的权限设计没有采用复杂的 OAuth 框架而是用一套轻量、清晰的角色 资源模型实现了从项目到内容字段级别的资源级权限控制。本文将从源码出发一步步拆解这套权限体系的实现原理帮助你真正读懂它的设计思路也为你在实际项目中进行权限扩展提供参考。权限体系总体架构从登录到授权的完整链路在 cloudbase-extension-cms 中一次受保护接口的请求要依次经过四道关卡每一道关卡职责单一、层层递进身份认证层确认你是谁校验登录态与用户身份角色加载层确认你是什么角色把角色和权限数据挂载到请求对象上服务与动作授权层确认你能不能用某个服务校验服务名与操作动作资源级授权层确认你能碰哪些具体资源精确到项目和内容资源 ID。这四层对应的核心源码文件都位于 packages/service/src/guards/ 与 packages/service/src/utils/permission.ts下面我们逐层深入。身份认证层如何识别登录用户第一道防线是 auth.guard.ts 中定义的GlobalAuthGuard它解决了谁在访问的问题。在云函数运行环境下它通过 CloudBase 的getEndUserInfo(TCB_UUID)拿到终端用户的身份信息在本地开发环境isDevEnv()下则会注入一个测试管理员身份方便开发者调试。拿到用户信息后守卫会到tcb-ext-cms-users集合中查询对应的用户记录如果用户不存在则直接返回 403。这段逻辑的意义在于身份认证只解决登录问题不解决授权问题。认证通过后用户记录会被挂载到request.cmsUser上供后续的权限校验使用。角色加载层管理员与普通用户的差异化处理第二道防线是 role.guard.ts 中的GlobalRoleGuard它负责把角色身份加工好塞进请求上下文。这里做了一个非常巧妙的性能优化内置角色走捷径自定义角色走数据库。逻辑如下如果用户是系统管理员administrator直接标记isAdmin true并将项目资源赋值为{*: *}即所有项目、所有资源的最高权限完全不需要查询数据库如果用户是项目管理员project:administrator同样直接放行isProjectAdmin true其余用户才需要从tcb-ext-cms-user-roles集合中按roles字段批量查询绑定的自定义角色并把角色中的权限列表挂载到cmsUser.userRoles。这样一来绝大多数用户每次请求只需要一次in查询就能拿到全部角色权限而且管理员请求完全零数据库开销性能与简洁兼得。服务与动作授权PermissionGuard 的匹配逻辑第三道防线是 permission.guard.ts 中的MixinPermissionGuard。它是整个体系中可插拔能力的关键——通过工厂函数PermissionGuard(service, roles)动态生成守卫并声明该接口所属的服务名。看看控制器里是怎么用的contents.controller.ts 使用UseGuards(PermissionGuard(content))schema.controller.ts 使用UseGuards(PermissionGuard(schema))operation.controller.ts 使用UseGuards(PermissionGuard(operation))需要管理员权限的接口则会传入第二个参数如PermissionGuard(role, [SYSTEM_ROLE_IDS.ADMIN])。守卫内的核心匹配逻辑有三条规则非常值得学习服务匹配权限中的service等于*或等于当前接口声明的服务名才通过动作匹配动作来源是路由处理函数的函数名如get、create、update、delete、set权限中的action包含*、或update兼容set前缀、或通过正则匹配当前动作角色兜底管理员直接放行普通用户必须命中某条角色权限才允许访问。资源级权限核心checkAccessAndGetResource 源码解读前面三层解决了服务能不能用而真正实现资源级权限的是 permission.ts 中的checkAccessAndGetResource函数。它是整个权限体系中最精华的一段代码核心逻辑可以概括为三步第一步校验项目访问权限。用户的projectResource是一个{ projectId: [resourceId, ...] }结构函数会过滤出当前项目 ID 或通配符*对应的资源如果用户连项目都不可见直接抛出您没有此项目的访问权限。第二步校验具体资源。如果请求中携带了resourceId则检查它是否在可访问资源列表中同样支持*通配。这里的*设计非常实用一个角色可以只对某个项目授权全部资源也可以对全部项目授权某个具体内容模型。第三步校验资源 动作组合。这一步会把用户所有角色的权限逐条比对先过滤出resource包含*或当前资源 ID 的权限再检查其中的action是否与当前操作匹配匹配规则与守卫层保持一致*全通、update兼容set、正则匹配。最终函数返回*或可访问的资源列表业务层就可以据此对数据做进一步的过滤处理。权限数据模型与内置角色设计理解了校验逻辑我们再来看权限的数据结构。在 packages/service/typings/index.d.ts 中定义了非常清晰的模型UserRole用户角色包含角色名、描述、权限列表、类型Permission权限规则由projectId项目、service服务、resource资源、action动作、effect允许/拒绝五个维度组成。这其实就是一套典型的RBAC基于角色的访问控制 资源维度扩展模型并且对通配符组合做了约束projectId为*时resource必须为*避免出现所有项目但只有部分资源这种矛盾配置。内置的系统角色定义在 constants.ts 的SystemUserRoles中共四种系统管理员administrator所有服务、所有项目、所有资源的全量权限项目管理员project:administrator与系统管理员权限一致但语义上限定在项目范围内运营人员operator内容服务 运营工具服务的全量权限内容管理员content:administrator仅内容服务的全量权限。前端如何落地权限控制后端校验只是权限体系的一半前端还要把权限翻译成可见可操作的界面。cloudbase-extension-cms 的管理后台packages/admin基于 Umi 的useAccess与Access组件实现页面级权限控制核心在 SecurityWrapper/index.tsx根据路由声明的access判断当前用户是否有权进入页面无权时展示 403 提示页。而在 RolePermission.tsx 中管理员可以可视化地为角色配置service、projectId、resource与action配置结果与后端数据结构一一对应真正实现了所见即所得的权限管理。总结一套值得借鉴的轻量权限范式纵观 cloudbase-extension-cms 的权限体系实现它的设计精髓可以归纳为三点职责分离认证、角色加载、服务授权、资源授权四层解耦每一层都可以独立测试与替换通配符驱动的资源模型用*表达全部让权限配置既灵活又简洁从项目级到资源级无缝覆盖可插拔的守卫工厂PermissionGuard(service, roles)让新增一个受保护的服务只需一行装饰器扩展成本极低。对于正在构建自己 CMS 或后台系统的开发者这套服务 资源 动作的三元组权限模型以及它对应的守卫链路是一份非常值得直接参考的开源实现。如果你也在寻找一套既能快速上手、又支持精细资源级控制的权限方案不妨把 cloudbase-extension-cms 的这套设计作为起点。【免费下载链接】cloudbase-extension-cms 一站式云端内容管理系统 - An open source Node.js headless cms based on CloudBase项目地址: https://gitcode.com/gh_mirrors/cl/cloudbase-extension-cms创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表