☰
权限管理怎么做?从“资格”与“空间”双维度设计一套可落地的权限体系
2026/10/15 14:00:46 网站建设 项目流程

1. 引言

权限管理是几乎所有多用户系统的核心难题。很多团队在初期只做“登录 + 角色”,上线后才发现:用户 A 能看用户 B 的私有数据、两个部门共用了同一份资源却互相覆盖、离职员工的权限迟迟没有回收……这些问题的根源,往往在于没有把“用户资格”和“资源空间”这两个维度分开设计。

本文从你提出的两个关键诉求出发——每个用户具有自己使用权限资源的资格、多个用户共同占有同一个空间——梳理一套可落地的权限模型,并给出数据库设计与代码示例。

2. 先厘清两个核心概念:资格(Entitlement)与空间(Space)

在动手设计之前,先把需求拆成两个正交的维度:

  • 资格(Entitlement):描述“某个用户能不能做某件事”。例如“张三可以编辑文档”“李四可以管理成员”。它回答的是Who can do What。
  • 空间(Space):描述“资源归属于哪个容器”。例如“项目 A 的文档库”“团队 B 的共享文件夹”。它回答的是Where the resource lives。

你提到的“每个用户具有自己使用权限资源的资格”,本质是资格要落到用户个体;“共同占有同样的空间”,本质是多个用户共享同一个资源容器。

把这两个维度分开,就能避免最常见的错误:把“谁能访问”和“资源在哪”混在一张表里,导致共享空间里每个人的权限无法独立控制。

3. 推荐模型:RBAC + 资源空间隔离

业界最稳妥的组合是RBAC(基于角色的访问控制)+ 资源空间(Space)隔离:

  • 用RBAC管理“资格”:用户 → 角色 → 权限点。
  • 用Space管理“空间”:资源挂在某个 Space 下,Space 再与用户/角色建立授权关系。

这样既保留了角色的复用性,又能做到“同一个空间里,不同用户拥有不同资格”。

3.1 核心实体

实体说明示例
User用户张三
Role角色(一组权限的集合)管理员、编辑者、访客
Permission权限点(最小操作单元)doc:edit、doc:view
Space资源空间容器项目 A、团队 B
SpaceMember空间成员(用户在某空间内的角色)张三在项目 A 中是编辑者

3.2 关键设计:空间成员表

“共同占有同一个空间”的核心落点,就是SpaceMember这张表。它把“用户”和“空间”关联起来,并记录该用户在这个空间内的角色:

CREATETABLEspace_member(idBIGINTPRIMARYKEYAUTO_INCREMENT,space_idBIGINTNOTNULLCOMMENT'空间ID',user_idBIGINTNOTNULLCOMMENT'用户ID',role_idBIGINTNOTNULLCOMMENT'角色ID(在该空间内生效)',created_atDATETIMEDEFAULTCURRENT_TIMESTAMP,UNIQUEKEYuk_space_user(space_id,user_id))COMMENT'空间成员表:用户在某空间内的资格';

通过这张表,你可以回答两个关键问题:

  • “张三在项目 A 里能做什么?” → 查space_member得到角色,再映射到权限点。
  • “项目 A 里有哪些成员?” → 按space_id查space_member。

4. 权限判断的核心流程

当用户发起一次操作(比如“编辑项目 A 的文档”)时,判断流程如下:

  1. 找到资源所属的Space。
  2. 查space_member,得到该用户在这个 Space 内的Role。
  3. 由 Role 映射出Permission集合。
  4. 判断所需权限点是否在集合中。
publicclassPermissionService{privatefinalSpaceMemberMapperspaceMemberMapper;privatefinalRolePermissionMapperrolePermissionMapper;publicbooleancheckPermission(LonguserId,LongspaceId,StringpermissionCode){// 1. 用户在空间内的角色SpaceMembermember=spaceMemberMapper.findBySpaceIdAndUserId(spaceId,userId);if(member==null){returnfalse;// 不是空间成员,默认无权限}// 2. 角色对应的权限点List<String>codes=rolePermissionMapper.findPermissionCodesByRoleId(member.getRoleId());returncodes.contains(permissionCode);}}

5. 如何兼顾“个人资格”与“共享空间”

你提到的两个诉求,在模型里分别对应两种授权方式:

5.1 个人专属资格

当某个用户拥有独立于任何空间的资格时(例如“全局管理员”“仅查看自己的数据”),可以:

  • 在user_role表中记录用户的全局角色;
  • 或在space_member中为每个用户创建一个私有空间(Personal Space),把个人资源挂进去。
CREATETABLEuser_role(idBIGINTPRIMARYKEYAUTO_INCREMENT,user_idBIGINTNOTNULL,role_idBIGINTNOTNULL,UNIQUEKEYuk_user_role(user_id,role_id))COMMENT'用户全局角色表:与空间无关的资格';

5.2 共享空间内的差异化资格

多个用户共同占有同一个 Space,但各自资格不同:

用户空间角色可执行操作
张三项目 A编辑者编辑、评论
李四项目 A访客仅查看
王五项目 A管理员编辑、删除、管理成员

这正是space_member表的价值:同一个 space_id,不同 user_id,不同 role_id。

6. 权限判断的完整时序

数据库PermissionService业务接口用户数据库PermissionService业务接口用户请求编辑项目A的文档checkPermission(userId, spaceId, "doc:edit")查询 space_member返回角色 roleId查询 role_permission返回权限点集合是否包含 "doc:edit"允许 / 拒绝

7. 常见坑与建议

  • 不要把权限写死在业务代码里:用if (user.isAdmin())这种散落判断,后期会失控。统一走权限点校验。
  • 空间删除前先清理成员关系:避免产生孤儿数据。
  • 权限点要足够细:至少拆到“查看 / 编辑 / 删除 / 管理成员”级别,方便后续做细粒度控制。
  • 缓存角色-权限映射:权限判断是高频操作,建议把role_permission缓存到 Redis,减少数据库压力。
  • 超管与空间管理员分开:全局超管走user_role,空间管理员走space_member,两者互不干扰。

8. 总结

权限管理的核心,是把“资格”和“空间”两个维度解耦:

  • 资格用 RBAC 管理,落到用户个体;
  • 空间用 Space 容器管理,多个用户通过space_member共享同一空间,并在空间内拥有各自独立的角色。

这样既满足了“每个用户具有自己使用权限资源的资格”,也实现了“共同占有同样的空间”。按这个模型落地,后续无论是加新空间、调成员角色,还是做细粒度权限,都能平滑扩展。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询