You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

30 KiB

权限体系模型

**本文引用的文件** - [AuthUser.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthUser.java) - [SysRole.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRole.java) - [SysMenu.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysMenu.java) - [SysDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysDept.java) - [SysUserRole.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserRole.java) - [SysRoleMenu.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRoleMenu.java) - [SysUserDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserDept.java) - [DataScopeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.java) - [MenuTypeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuTypeEnum.java) - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java) - [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java) - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java) - [PermissionServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/PermissionServiceImpl.java) - [SysMenuServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysMenuServiceImpl.java) - [SysDeptServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysDeptServiceImpl.java) - [SysRoleServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysRoleServiceImpl.java) - [AuthUserServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthUserServiceImpl.java) - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)

目录

  1. 引言
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考虑
  8. 故障排查指南
  9. 结论
  10. 附录

引言

本文件面向权限系统的数据模型设计与实现,围绕RBAC(基于角色的访问控制)模型,系统化阐述角色、菜单、部门及其关联关系的数据结构设计。文档涵盖用户-角色、角色-菜单、用户-部门的关联表设计;说明权限继承机制、数据范围控制与菜单权限过滤的数据库支持;提供实体关系图、外键约束建议与索引优化策略,为权限系统的开发与扩展提供完整参考。

项目结构

权限相关实体、枚举、服务与拦截器主要分布在认证模块与基础模块中:

  • 认证模块(crm-auth):包含用户、角色、菜单、部门等实体定义,以及权限计算、菜单树构建、数据范围拦截等实现。
  • 基础模块(crm-base):提供通用基类、数据可见性上下文、数据范围注解与工具方法、MyBatis-Plus配置与SQL注入器等。
graph TB
subgraph "认证模块"
A["AuthUser"] --> B["SysUserRole"]
C["SysRole"] --> D["SysRoleMenu"]
E["SysMenu"]
F["SysDept"] --> G["SysUserDept"]
H["PermissionServiceImpl"]
I["SysMenuServiceImpl"]
J["SysDeptServiceImpl"]
K["SysRoleServiceImpl"]
L["AuthUserServiceImpl"]
M["DataScopeInterceptor"]
N["DataScopeTables"]
end
subgraph "基础模块"
O["BaseEntity"]
P["OwnedEntity"]
Q["DataScope"]
R["DataScopeHelper"]
S["DataScopeLevel"]
T["DataVisibilityContext"]
U["SecurityUtils"]
V["LoginUser"]
W["MybatisPlusConfig"]
X["CrmSqlInjector"]
end
A --> O
C --> O
E --> O
F --> O
B --> O
D --> O
G --> O
H --> Q
I --> E
J --> F
K --> C
L --> A
M --> R
M --> S
M --> T
W --> X

图表来源

  • AuthUser.java
  • SysRole.java
  • SysMenu.java
  • SysDept.java
  • SysUserRole.java
  • SysRoleMenu.java
  • SysUserDept.java
  • PermissionServiceImpl.java
  • SysMenuServiceImpl.java
  • SysDeptServiceImpl.java
  • SysRoleServiceImpl.java
  • AuthUserServiceImpl.java
  • DataScopeInterceptor.java
  • DataScopeTables.java
  • BaseEntity.java
  • OwnedEntity.java
  • DataScope.java
  • DataScopeHelper.java
  • DataScopeLevel.java
  • DataVisibilityContext.java
  • SecurityUtils.java
  • LoginUser.java
  • MybatisPlusConfig.java
  • CrmSqlInjector.java

章节来源

  • AuthUser.java
  • SysRole.java
  • SysMenu.java
  • SysDept.java
  • SysUserRole.java
  • SysRoleMenu.java
  • SysUserDept.java
  • DataScopeEnum.java
  • MenuTypeEnum.java
  • DataScope.java
  • DataScopeHelper.java
  • DataScopeLevel.java
  • DataVisibilityContext.java
  • SecurityUtils.java
  • LoginUser.java
  • BaseEntity.java
  • OwnedEntity.java
  • MybatisPlusConfig.java
  • CrmSqlInjector.java
  • PermissionServiceImpl.java
  • SysMenuServiceImpl.java
  • SysDeptServiceImpl.java
  • SysRoleServiceImpl.java
  • AuthUserServiceImpl.java
  • DataScopeInterceptor.java
  • DataScopeTables.java

核心组件

  • 实体模型
    • 用户:AuthUser,承载登录账号、身份标识、状态等基础信息。
    • 角色:SysRole,承载角色名称、编码、描述、数据范围等。
    • 菜单:SysMenu,承载菜单层级、类型、路径、图标、排序、可见性等。
    • 部门:SysDept,承载部门名称、上级部门、排序、状态等。
    • 关联表:SysUserRole(用户-角色)、SysRoleMenu(角色-菜单)、SysUserDept(用户-部门)。
  • 枚举与常量
    • DataScopeEnum:数据范围类型(如全部、本部门、本部门及子部门、仅本人等)。
    • MenuTypeEnum:菜单类型(目录、菜单、按钮等),用于前端渲染与权限判断。
  • 安全与数据范围
    • DataScope注解:标注在查询方法上,声明数据范围级别。
    • DataScopeHelper/DataScopeLevel/DataVisibilityContext:数据范围解析与上下文管理。
    • SecurityUtils/LoginUser:当前登录用户上下文获取。
  • 基础设施
    • BaseEntity/OwnedEntity:通用字段(如创建时间、更新人、租户或归属等)。
    • MybatisPlusConfig/CrmSqlInjector:分页、自动填充、SQL注入增强。
    • DataScopeInterceptor/DataScopeTables:数据范围拦截与表级范围映射。

章节来源

  • AuthUser.java
  • SysRole.java
  • SysMenu.java
  • SysDept.java
  • SysUserRole.java
  • SysRoleMenu.java
  • SysUserDept.java
  • DataScopeEnum.java
  • MenuTypeEnum.java
  • DataScope.java
  • DataScopeHelper.java
  • DataScopeLevel.java
  • DataVisibilityContext.java
  • SecurityUtils.java
  • LoginUser.java
  • BaseEntity.java
  • OwnedEntity.java
  • MybatisPlusConfig.java
  • CrmSqlInjector.java
  • DataScopeInterceptor.java
  • DataScopeTables.java

架构总览

权限体系采用RBAC模型,结合菜单树与部门层级,形成“用户-角色-菜单”和“用户-部门”的双维度权限控制。数据范围通过注解与拦截器在SQL层动态拼接条件,实现细粒度的数据可见性控制。

classDiagram
class AuthUser {
+id
+username
+status
+...
}
class SysRole {
+id
+name
+code
+data_scope
+...
}
class SysMenu {
+id
+parent_id
+type
+path
+sort
+visible
+...
}
class SysDept {
+id
+parent_id
+name
+sort
+status
+...
}
class SysUserRole {
+user_id
+role_id
}
class SysRoleMenu {
+role_id
+menu_id
}
class SysUserDept {
+user_id
+dept_id
}
AuthUser --> SysUserRole : "多对多"
SysRole --> SysRoleMenu : "多对多"
SysMenu --> SysRoleMenu : "多对多"
AuthUser --> SysUserDept : "多对多"
SysDept --> SysUserDept : "多对多"

图表来源

  • AuthUser.java
  • SysRole.java
  • SysMenu.java
  • SysDept.java
  • SysUserRole.java
  • SysRoleMenu.java
  • SysUserDept.java

详细组件分析

RBAC权限模型与关联表设计

  • 用户-角色(SysUserRole)
    • 作用:将用户与角色建立多对多关系,支撑角色权限继承。
    • 关键字段:用户ID、角色ID。
    • 索引建议:联合唯一索引(user_id, role_id),查询用户角色时高效。
  • 角色-菜单(SysRoleMenu)
    • 作用:将角色与菜单建立多对多关系,决定角色可访问的菜单与按钮。
    • 关键字段:角色ID、菜单ID。
    • 索引建议:联合唯一索引(role_id, menu_id),按角色加载菜单树时高效。
  • 用户-部门(SysUserDept)
    • 作用:将用户与部门建立多对多关系,支撑数据范围与组织视图。
    • 关键字段:用户ID、部门ID。
    • 索引建议:联合唯一索引(user_id, dept_id),按用户加载部门列表时高效。

章节来源

  • SysUserRole.java
  • SysRoleMenu.java
  • SysUserDept.java

菜单树结构与类型

  • 菜单(SysMenu)
    • 层级结构:通过父ID(parent_id)自引用形成树形结构,根节点parent_id为空或特定值。
    • 类型(MenuTypeEnum):区分目录、菜单、按钮等,用于前端渲染与权限校验。
    • 可见性与排序:visible与sort字段控制展示顺序与可见性。
  • 菜单权限过滤
    • 服务层(SysMenuServiceImpl)负责根据角色与用户权限构建菜单树,过滤无权限节点。
    • 权限计算(PermissionServiceImpl)汇总用户角色与角色菜单,生成权限集合。
flowchart TD
Start(["开始"]) --> LoadRoles["加载用户角色"]
LoadRoles --> LoadMenus["加载角色对应菜单"]
LoadMenus --> BuildTree["构建菜单树"]
BuildTree --> FilterVisible{"是否可见?"}
FilterVisible --> |否| Skip["跳过该节点"]
FilterVisible --> |是| Keep["保留该节点"]
Skip --> Next["处理下一个节点"]
Keep --> Next
Next --> Done(["完成"])

图表来源

  • SysMenuServiceImpl.java
  • PermissionServiceImpl.java
  • SysMenu.java
  • MenuTypeEnum.java

章节来源

  • SysMenu.java
  • MenuTypeEnum.java
  • SysMenuServiceImpl.java
  • PermissionServiceImpl.java

部门层级关系与数据范围

  • 部门(SysDept)
    • 层级结构:通过父ID(parent_id)自引用形成树形结构,便于组织视图与数据范围推导。
    • 状态与排序:status与sort字段控制显示与顺序。
  • 数据范围(DataScopeEnum)
    • 类型包括:全部、本部门、本部门及子部门、仅本人等,影响查询时的数据可见性。
    • 注解(DataScope)与级别(DataScopeLevel)配合使用,声明方法级的数据范围策略。
    • 上下文(DataVisibilityContext)维护当前请求的数据可见范围。
    • 辅助(DataScopeHelper)解析范围并生成SQL片段。
    • 拦截器(DataScopeInterceptor)在SQL执行前注入WHERE条件。
    • 表级映射(DataScopeTables)定义哪些表需要应用数据范围。
sequenceDiagram
participant Client as "客户端"
participant Controller as "业务控制器"
participant Service as "业务服务"
participant Interceptor as "数据范围拦截器"
participant DB as "数据库"
Client->>Controller : 发起查询请求
Controller->>Service : 调用带@DataScope的方法
Service->>Interceptor : 进入拦截器
Interceptor->>Interceptor : 解析DataScopeLevel与上下文
Interceptor->>DB : 注入数据范围WHERE条件
DB-->>Interceptor : 返回受限结果集
Interceptor-->>Service : 返回结果
Service-->>Controller : 返回数据
Controller-->>Client : 响应数据

图表来源

  • DataScope.java
  • DataScopeLevel.java
  • DataVisibilityContext.java
  • DataScopeHelper.java
  • DataScopeInterceptor.java
  • DataScopeTables.java

章节来源

  • SysDept.java
  • DataScopeEnum.java
  • DataScope.java
  • DataScopeLevel.java
  • DataVisibilityContext.java
  • DataScopeHelper.java
  • DataScopeInterceptor.java
  • DataScopeTables.java

用户-角色-菜单权限计算流程

  • 用户(AuthUser)通过SysUserRole关联多个角色。
  • 角色(SysRole)通过SysRoleMenu关联多个菜单。
  • 权限计算(PermissionServiceImpl)聚合用户角色与角色菜单,生成权限集合,供前端菜单渲染与后端接口鉴权使用。
  • 用户服务(AuthUserServiceImpl)在登录或会话初始化时加载用户权限。
sequenceDiagram
participant User as "用户"
participant AuthService as "认证服务"
participant PermService as "权限服务"
participant RoleMapper as "角色映射"
participant MenuMapper as "菜单映射"
User->>AuthService : 登录
AuthService->>PermService : 计算权限(用户ID)
PermService->>RoleMapper : 查询用户角色
RoleMapper-->>PermService : 角色列表
PermService->>MenuMapper : 查询角色菜单
MenuMapper-->>PermService : 菜单列表
PermService-->>AuthService : 权限集合
AuthService-->>User : 返回登录结果与权限

图表来源

  • AuthUserServiceImpl.java
  • PermissionServiceImpl.java
  • SysRole.java
  • SysMenu.java
  • SysUserRole.java
  • SysRoleMenu.java

章节来源

  • AuthUserServiceImpl.java
  • PermissionServiceImpl.java
  • SysRole.java
  • SysMenu.java
  • SysUserRole.java
  • SysRoleMenu.java

实体关系图(ERD)

erDiagram
AUTH_USER {
bigint id PK
varchar username UK
int status
datetime created_at
datetime updated_at
}
SYS_ROLE {
bigint id PK
varchar name
varchar code UK
int data_scope
datetime created_at
datetime updated_at
}
SYS_MENU {
bigint id PK
bigint parent_id FK
enum type
varchar path
int sort
boolean visible
datetime created_at
datetime updated_at
}
SYS_DEPT {
bigint id PK
bigint parent_id FK
varchar name
int sort
int status
datetime created_at
datetime updated_at
}
SYS_USER_ROLE {
bigint user_id FK
bigint role_id FK
}
SYS_ROLE_MENU {
bigint role_id FK
bigint menu_id FK
}
SYS_USER_DEPT {
bigint user_id FK
bigint dept_id FK
}
AUTH_USER ||--o{ SYS_USER_ROLE : "拥有"
SYS_ROLE ||--o{ SYS_USER_ROLE : "分配给"
SYS_ROLE ||--o{ SYS_ROLE_MENU : "包含"
SYS_MENU ||--o{ SYS_ROLE_MENU : "被授权"
AUTH_USER ||--o{ SYS_USER_DEPT : "属于"
SYS_DEPT ||--o{ SYS_USER_DEPT : "包含"

图表来源

  • AuthUser.java
  • SysRole.java
  • SysMenu.java
  • SysDept.java
  • SysUserRole.java
  • SysRoleMenu.java
  • SysUserDept.java

依赖关系分析

  • 实体依赖
    • AuthUser、SysRole、SysMenu、SysDept均继承BaseEntity,可能还继承OwnedEntity以支持归属字段。
    • 关联表(SysUserRole、SysRoleMenu、SysUserDept)作为中间表,承载多对多关系。
  • 服务与拦截器依赖
    • PermissionServiceImpl依赖角色与菜单映射,生成权限集合。
    • SysMenuServiceImpl依赖菜单实体与权限集合,构建菜单树。
    • DataScopeInterceptor依赖DataScopeHelper、DataScopeLevel、DataVisibilityContext与DataScopeTables,在SQL层注入数据范围条件。
  • 基础设施依赖
    • MybatisPlusConfig与CrmSqlInjector提供分页、自动填充与SQL增强能力。
graph LR
AuthUser --> BaseEntity
SysRole --> BaseEntity
SysMenu --> BaseEntity
SysDept --> BaseEntity
SysUserRole --> AuthUser
SysUserRole --> SysRole
SysRoleMenu --> SysRole
SysRoleMenu --> SysMenu
SysUserDept --> AuthUser
SysUserDept --> SysDept
PermissionServiceImpl --> SysRole
PermissionServiceImpl --> SysMenu
SysMenuServiceImpl --> SysMenu
DataScopeInterceptor --> DataScopeHelper
DataScopeInterceptor --> DataScopeLevel
DataScopeInterceptor --> DataVisibilityContext
DataScopeInterceptor --> DataScopeTables
MybatisPlusConfig --> CrmSqlInjector

图表来源

  • BaseEntity.java
  • OwnedEntity.java
  • SysUserRole.java
  • SysRoleMenu.java
  • SysUserDept.java
  • PermissionServiceImpl.java
  • SysMenuServiceImpl.java
  • DataScopeInterceptor.java
  • DataScopeHelper.java
  • DataScopeLevel.java
  • DataVisibilityContext.java
  • DataScopeTables.java
  • MybatisPlusConfig.java
  • CrmSqlInjector.java

章节来源

  • BaseEntity.java
  • OwnedEntity.java
  • SysUserRole.java
  • SysRoleMenu.java
  • SysUserDept.java
  • PermissionServiceImpl.java
  • SysMenuServiceImpl.java
  • DataScopeInterceptor.java
  • DataScopeHelper.java
  • DataScopeLevel.java
  • DataVisibilityContext.java
  • DataScopeTables.java
  • MybatisPlusConfig.java
  • CrmSqlInjector.java

性能考虑

  • 索引优化
    • 关联表联合唯一索引:(user_id, role_id)、(role_id, menu_id)、(user_id, dept_id),提升多对多查询效率。
    • 菜单树查询:为parent_id与type建立复合索引,加速菜单树构建与过滤。
    • 数据范围:为涉及部门与用户的字段建立索引,减少全表扫描。
  • SQL注入与分页
    • 使用MybatisPlusConfig与CrmSqlInjector进行分页与自动填充,避免手写复杂SQL。
    • 数据范围拦截器在SQL层注入WHERE条件,避免在应用层过滤大量数据。
  • 缓存与预取
    • 菜单树与权限集合可在登录后缓存,减少重复计算。
    • 部门树可缓存,降低频繁查询开销。

[本节为通用性能指导,不直接分析具体文件]

故障排查指南

  • 权限缺失
    • 检查用户是否分配了角色(SysUserRole)。
    • 检查角色是否包含所需菜单(SysRoleMenu)。
    • 确认菜单可见性(SysMenu.visible)与类型(MenuTypeEnum)。
  • 数据范围异常
    • 检查方法是否标注@DataScope,且级别正确(DataScopeLevel)。
    • 确认DataVisibilityContext是否正确设置当前用户与部门。
    • 检查DataScopeTables是否包含目标表。
  • 菜单树构建问题
    • 检查parent_id层级是否正确,是否存在孤立节点。
    • 确认权限集合是否包含必要菜单项。

章节来源

  • SysUserRole.java
  • SysRoleMenu.java
  • SysMenu.java
  • MenuTypeEnum.java
  • DataScope.java
  • DataScopeLevel.java
  • DataVisibilityContext.java
  • DataScopeTables.java

结论

本权限体系以RBAC为核心,结合菜单树与部门层级,实现了灵活的权限控制与数据范围管理。通过关联表与枚举、注解与拦截器的协同,系统在数据库层与应用层共同保障权限与数据的准确性与性能。建议在开发中严格遵循索引与SQL注入规范,合理使用缓存,确保系统在高并发场景下的稳定性与可扩展性。

[本节为总结性内容,不直接分析具体文件]

附录

  • 最佳实践
    • 为所有关联表建立联合唯一索引,避免重复数据与低效查询。
    • 使用统一的基类(BaseEntity/OwnedEntity)管理公共字段,保证一致性。
    • 在方法级使用@DataScope明确数据范围,避免硬编码WHERE条件。
    • 菜单树构建与权限计算应在登录后缓存,减少重复计算。
    • 定期审计角色与菜单分配,清理无效权限。

[本节为通用指导,不直接分析具体文件]