# 权限管理系统
**本文引用的文件**
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
- [application.yml](file://crm-app/src/main/resources/application.yml)
- [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java)
- [application.yml](file://crm-auth/src/main/resources/application.yml)
- [PermissionConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.java)
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
- [DataInitializer.java](file://crm-auth/src/main/java/com/crm/auth/config/DataInitializer.java)
- [AuthConstants.java](file://crm-auth/src/main/java/com/crm/auth/constant/AuthConstants.java)
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
- [SystemController.java](file://crm-auth/src/main/java/com/crm/auth/controller/SystemController.java)
- [AuthIdentity.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthIdentity.java)
- [AuthUser.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthUser.java)
- [SysDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysDept.java)
- [SysMenu.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysMenu.java)
- [SysRole.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRole.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)
- [SysUserRole.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserRole.java)
- [DataScopeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.java)
- [IdentityTypeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/IdentityTypeEnum.java)
- [MenuTypeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuTypeEnum.java)
- [LoginParam.java](file://crm-auth/src/main/java/com/crm/auth/domain/param/LoginParam.java)
- [LoginResultDTO.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/LoginResultDTO.java)
- [UserInfoDTO.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/UserInfoDTO.java)
- [AuthIdentityMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/AuthIdentityMapper.java)
- [AuthUserMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/AuthUserMapper.java)
- [SysDeptMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/SysDeptMapper.java)
- [SysMenuMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/SysMenuMapper.java)
- [SysRoleMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/SysRoleMapper.java)
- [SysRoleMenuMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/SysRoleMenuMapper.java)
- [SysUserDeptMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/SysUserDeptMapper.java)
- [SysUserRoleMapper.java](file://crm-auth/src/main/java/com/crm/auth/mapper/SysUserRoleMapper.java)
- [AuthLoginUser.java](file://crm-auth/src/main/java/com/crm/auth/security/AuthLoginUser.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)
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
- [SecurityExceptionHandlers.java](file://crm-auth/src/main/java/com/crm/auth/security/SecurityExceptionHandlers.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
- [DingTalkAuthClient.java](file://crm-auth/src/main/java/com/crm/auth/service/client/DingTalkAuthClient.java)
- [ThirdPartyAuthClient.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyAuthClient.java)
- [ThirdPartyAuthClientFactory.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyAuthClientFactory.java)
- [ThirdPartyUserInfo.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyUserInfo.java)
- [AuthIdentityServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthIdentityServiceImpl.java)
- [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java)
- [AuthUserServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthUserServiceImpl.java)
- [PermissionServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/PermissionServiceImpl.java)
- [SysDeptServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysDeptServiceImpl.java)
- [SysMenuServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysMenuServiceImpl.java)
- [SysRoleServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysRoleServiceImpl.java)
- [DeptTreeCache.java](file://crm-auth/src/main/java/com/crm/auth/service/DeptTreeCache.java)
- [IAuthIdentityService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthIdentityService.java)
- [IAuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
- [IAuthUserService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthUserService.java)
- [ISysDeptService.java](file://crm-auth/src/main/java/com/crm/auth/service/ISysDept.java)
- [ISysMenuService.java](file://crm-auth/src/main/java/com/crm/auth/service/ISysMenuService.java)
- [ISysRoleService.java](file://crm-auth/src/main/java/com/crm/auth/service/ISysRoleService.java)
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java)
- [CorsConfig.java](file://crm-base/src/main/java/com/crm/base/config/CorsConfig.java)
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
- [CustomIdGenerator.java](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java)
- [InsertBatchOnDuplicateKeyUpdate.java](file://crm-base/src/main/java/com/crm/base/config/InsertBatchOnDuplicateKeyUpdate.java)
- [JacksonConfig.java](file://crm-base/src/main/java/com/crm/base/config/JacksonConfig.java)
- [Knife4jConfig.java](file://crm-base/src/main/java/com/crm/base/config/Knife4jConfig.java)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java)
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
- [ScheduledTaskProperties.java](file://crm-base/src/main/java/com/crm/base/config/ScheduledTaskProperties.java)
- [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java)
- [SnowflakeProperties.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java)
- [CommonConstants.java](file://crm-base/src/main/java/com/crm/base/constant/CommonConstants.java)
- [BaseDTO.java](file://crm-base/src/main/java/com/crm/base/domain/dto/BaseDTO.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)
- [HasValueEnum.java](file://crm-base/src/main/java/com/crm/base/domain/enums/HasValueEnum.java)
- [StatusEnum.java](file://crm-base/src/main/java/com/crm/base/domain/enums/StatusEnum.java)
- [BusinessErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/BusinessErrorException.java)
- [MissingParameterException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/MissingParameterException.java)
- [PermissionErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/PermissionErrorException.java)
- [ResourceNotExistException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/ResourceNotExistException.java)
- [BaseParam.java](file://crm-base/src/main/java/com/crm/base/domain/param/BaseParam.java)
- [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java)
- [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java)
- [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java)
- [TraceIdFilter.java](file://crm-base/src/main/java/com/crm/base/filter/TraceIdFilter.java)
- [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java)
- [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.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)
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java)
- [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java)
- [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java)
- [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java)
- [AssertUtils.java](file://crm-base/src/main/java/com/crm/base/utils/AssertUtils.java)
- [BeanCopyUtils.java](file://crm-base/src/main/java/com/crm/base/utils/BeanCopyUtils.java)
- [EnumUtils.java](file://crm-base/src/main/java/com/crm/base/utils/EnumUtils.java)
- [ExcelUtil.java](file://crm-base/src/main/java/com/crm/base/utils/ExcelUtil.java)
- [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java)
- [ServletUtils.java](file://crm-base/src/main/java/com/crm/base/utils/ServletUtils.java)
- [TreeUtils.java](file://crm-base/src/main/java/com/crm/base/utils/TreeUtils.java)
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考虑](#性能考虑)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件为基于RBAC(角色-资源)的权限管理系统文档,覆盖角色管理、菜单权限控制与数据权限范围控制。重点说明实体设计(如 SysRole、SysMenu)、权限校验逻辑(PermissionServiceImpl)、数据权限类型(DataScopeEnum),以及权限注解使用、动态权限加载与权限缓存机制的实现细节和配置方法。读者可据此快速理解系统权限模型并正确扩展与使用。
## 项目结构
本项目采用多模块组织:
- crm-app:应用启动入口与全局配置
- crm-auth:认证与权限核心模块,包含RBAC实体、服务、安全拦截、第三方登录等
- crm-base:公共基础能力(异常、工具、通用配置、数据可见性上下文等)
- crm-file:文件服务(与本权限文档无直接关联)
```mermaid
graph TB
subgraph "应用层"
APP["crm-app
启动与应用配置"]
end
subgraph "认证与权限"
AUTH["crm-auth
RBAC实体/服务/安全/客户端"]
end
subgraph "基础能力"
BASE["crm-base
异常/工具/通用配置/数据可见性"]
end
APP --> AUTH
AUTH --> BASE
```
图表来源
- [CrmAppApplication.java:1-200](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java#L1-L200)
- [AuthApplication.java:1-200](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java#L1-L200)
章节来源
- [CrmAppApplication.java:1-200](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java#L1-L200)
- [AuthApplication.java:1-200](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java#L1-L200)
## 核心组件
- RBAC 实体
- SysRole:角色定义,承载角色标识、名称、状态等元信息
- SysMenu:菜单与按钮等资源定义,支持层级结构与类型区分
- SysUserRole、SysRoleMenu:用户-角色、角色-菜单的多对多关系表
- SysDept、SysUserDept:部门与用户部门关系,用于数据权限范围
- 权限服务
- PermissionServiceImpl:实现权限校验、菜单树构建、数据权限注入
- SysRoleServiceImpl、SysMenuServiceImpl:角色与菜单的CRUD与树形结构处理
- 安全与拦截
- SecurityConfig、JwtAuthenticationFilter:认证流程与JWT过滤
- DataScopeInterceptor、DataScopeTables:数据权限拦截与SQL改写
- AuthLoginUser、TokenService:当前登录用户上下文与令牌操作
- 数据权限
- DataScopeEnum:数据权限范围枚举(如全部、本部门、本部门及子部门、仅本人等)
- DataScope(注解)、DataScopeHelper、DataVisibilityContext:注解驱动的数据可见性控制
章节来源
- [SysRole.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRole.java#L1-L200)
- [SysMenu.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysMenu.java#L1-L200)
- [SysUserRole.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserRole.java#L1-L200)
- [SysRoleMenu.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRoleMenu.java#L1-L200)
- [SysDept.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysDept.java#L1-L200)
- [SysUserDept.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserDept.java#L1-L200)
- [PermissionServiceImpl.java:1-200](file://crm-auth/src/main/java/com/crm/auth/service/impl/PermissionServiceImpl.java#L1-L200)
- [SysRoleServiceImpl.java:1-200](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysRoleServiceImpl.java#L1-L200)
- [SysMenuServiceImpl.java:1-200](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysMenuServiceImpl.java#L1-L200)
- [SecurityConfig.java:1-200](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java#L1-L200)
- [JwtAuthenticationFilter.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java#L1-L200)
- [DataScopeInterceptor.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java#L1-L200)
- [DataScopeTables.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java#L1-L200)
- [AuthLoginUser.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/AuthLoginUser.java#L1-L200)
- [TokenService.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java#L1-L200)
- [DataScopeEnum.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.java#L1-L200)
- [DataScope.java:1-200](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java#L1-L200)
- [DataScopeHelper.java:1-200](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java#L1-L200)
- [DataVisibilityContext.java:1-200](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java#L1-L200)
## 架构总览
下图展示认证与权限在请求链路中的关键交互:从JWT鉴权到权限校验、再到数据权限注入与SQL改写。
```mermaid
sequenceDiagram
participant Client as "客户端"
participant API as "控制器"
participant SecCfg as "SecurityConfig"
participant JwtFilt as "JwtAuthenticationFilter"
participant Perm as "PermissionServiceImpl"
participant DSI as "DataScopeInterceptor"
participant DB as "数据库"
Client->>API : "HTTP 请求"
API->>SecCfg : "路由匹配与授权规则"
SecCfg->>JwtFilt : "解析JWT并建立认证上下文"
JwtFilt-->>API : "已认证用户"
API->>Perm : "调用权限校验(菜单/按钮)"
Perm-->>API : "返回是否允许访问"
API->>DSI : "进入数据权限拦截"
DSI->>DB : "根据数据权限范围改写SQL"
DB-->>API : "返回受限结果集"
API-->>Client : "响应"
```
图表来源
- [SecurityConfig.java:1-200](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java#L1-L200)
- [JwtAuthenticationFilter.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java#L1-L200)
- [PermissionServiceImpl.java:1-200](file://crm-auth/src/main/java/com/crm/auth/service/impl/PermissionServiceImpl.java#L1-L200)
- [DataScopeInterceptor.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java#L1-L200)
## 详细组件分析
### RBAC 实体设计与关系
- SysRole:角色主实体,提供角色ID、编码、名称、状态等字段
- SysMenu:菜单/按钮资源实体,支持类型(菜单、按钮、目录等)、排序、路径、图标等
- SysUserRole、SysRoleMenu:多对多关系表,支撑“用户-角色”、“角色-菜单”的授权映射
- SysDept、SysUserDept:部门维度,配合数据权限范围进行数据隔离
```mermaid
erDiagram
SYS_ROLE {
bigint id PK
varchar code UK
varchar name
int status
datetime created_at
datetime updated_at
}
SYS_MENU {
bigint id PK
varchar type
varchar path
varchar icon
int sort
int status
bigint parent_id
datetime created_at
datetime updated_at
}
SYS_USER_ROLE {
bigint id PK
bigint user_id FK
bigint role_id FK
}
SYS_ROLE_MENU {
bigint id PK
bigint role_id FK
bigint menu_id FK
}
SYS_DEPT {
bigint id PK
varchar name
bigint parent_id
int status
}
SYS_USER_DEPT {
bigint id PK
bigint user_id FK
bigint dept_id FK
}
SYS_ROLE ||--o{ SYS_ROLE_MENU : "拥有"
SYS_MENU ||--o{ SYS_ROLE_MENU : "被授权"
SYS_USER ||--o{ SYS_USER_ROLE : "属于"
SYS_ROLE ||--o{ SYS_USER_ROLE : "分配给"
SYS_DEPT ||--o{ SYS_USER_DEPT : "包含"
SYS_USER ||--o{ SYS_USER_DEPT : "归属"
```
图表来源
- [SysRole.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRole.java#L1-L200)
- [SysMenu.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysMenu.java#L1-L200)
- [SysUserRole.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserRole.java#L1-L200)
- [SysRoleMenu.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRoleMenu.java#L1-L200)
- [SysDept.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysDept.java#L1-L200)
- [SysUserDept.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserDept.java#L1-L200)
章节来源
- [SysRole.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRole.java#L1-L200)
- [SysMenu.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysMenu.java#L1-L200)
- [SysUserRole.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserRole.java#L1-L200)
- [SysRoleMenu.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRoleMenu.java#L1-L200)
- [SysDept.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysDept.java#L1-L200)
- [SysUserDept.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserDept.java#L1-L200)
### 权限校验与动态菜单加载(PermissionServiceImpl)
- 权限校验流程
- 获取当前用户及其角色集合
- 根据角色聚合菜单与按钮权限
- 针对接口或按钮进行白名单/黑名单校验
- 动态菜单加载
- 按用户角色查询菜单树,过滤无效节点
- 生成前端导航所需的树形结构
- 缓存策略
- 以用户或角色为键缓存菜单树与权限集合
- 在角色/菜单变更时主动失效相关缓存
```mermaid
flowchart TD
Start(["进入权限校验"]) --> LoadUser["加载当前用户与角色"]
LoadUser --> CheckWhiteList{"是否在免检白名单?"}
CheckWhiteList --> |是| Allow["放行"]
CheckWhiteList --> |否| BuildPerms["构建权限集合(菜单/按钮)"]
BuildPerms --> HasPerm{"是否具备所需权限?"}
HasPerm --> |是| Allow
HasPerm --> |否| Deny["拒绝访问"]
Allow --> End(["结束"])
Deny --> End
```
图表来源
- [PermissionServiceImpl.java:1-200](file://crm-auth/src/main/java/com/crm/auth/service/impl/PermissionServiceImpl.java#L1-L200)
- [SysMenuServiceImpl.java:1-200](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysMenuServiceImpl.java#L1-L200)
- [SysRoleServiceImpl.java:1-200](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysRoleServiceImpl.java#L1-L200)
章节来源
- [PermissionServiceImpl.java:1-200](file://crm-auth/src/main/java/com/crm/auth/service/impl/PermissionServiceImpl.java#L1-L200)
- [SysMenuServiceImpl.java:1-200](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysMenuServiceImpl.java#L1-L200)
- [SysRoleServiceImpl.java:1-200](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysRoleServiceImpl.java#L1-L200)
### 数据权限范围控制(DataScopeEnum 与拦截器)
- 数据权限类型
- 全部数据、本部门数据、本部门及子部门数据、仅本人数据等
- 注解驱动
- 在方法上使用 @DataScope 指定数据范围与目标表
- 拦截与SQL改写
- DataScopeInterceptor 读取上下文中的数据权限范围
- DataScopeTables 维护表与列的映射关系
- 通过 MyBatis Plus 的 SQL 注入器自动追加 WHERE 条件
```mermaid
sequenceDiagram
participant Controller as "业务控制器"
participant Interceptor as "DataScopeInterceptor"
participant Helper as "DataScopeHelper"
participant Tables as "DataScopeTables"
participant MP as "MyBatisPlus注入器"
participant DB as "数据库"
Controller->>Interceptor : "进入受保护方法"
Interceptor->>Helper : "解析@DataScope参数"
Helper->>Tables : "查找表/列映射"
Tables-->>Helper : "返回映射信息"
Helper-->>MP : "生成数据权限WHERE片段"
MP-->>DB : "执行带限制的SQL"
DB-->>Controller : "返回受限结果"
```
图表来源
- [DataScope.java:1-200](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java#L1-L200)
- [DataScopeInterceptor.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java#L1-L200)
- [DataScopeTables.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java#L1-L200)
- [DataScopeHelper.java:1-200](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java#L1-L200)
- [CrmSqlInjector.java:1-200](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java#L1-L200)
章节来源
- [DataScopeEnum.java:1-200](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.java#L1-L200)
- [DataScope.java:1-200](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java#L1-L200)
- [DataScopeInterceptor.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java#L1-L200)
- [DataScopeTables.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java#L1-L200)
- [DataScopeHelper.java:1-200](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java#L1-L200)
- [CrmSqlInjector.java:1-200](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java#L1-L200)
### 认证与安全配置(SecurityConfig、JwtAuthenticationFilter、TokenService)
- SecurityConfig:定义URL白名单、授权规则、跨域与异常处理器
- JwtAuthenticationFilter:解析JWT,填充认证上下文
- TokenService:生成、刷新、注销令牌,维护会话状态
```mermaid
classDiagram
class SecurityConfig {
+configure(http) void
+cors() CorsConfigurationSource
+exceptionHandler() SecurityExceptionHandlers
}
class JwtAuthenticationFilter {
+doFilter(request, response, chain) void
+parseToken(request) String
+setContext(token) void
}
class TokenService {
+createToken(user) String
+refreshToken(token) String
+logout(token) void
+validate(token) boolean
}
SecurityConfig --> JwtAuthenticationFilter : "注册过滤器"
JwtAuthenticationFilter --> TokenService : "验证/解析令牌"
```
图表来源
- [SecurityConfig.java:1-200](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java#L1-L200)
- [JwtAuthenticationFilter.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java#L1-L200)
- [TokenService.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java#L1-L200)
章节来源
- [SecurityConfig.java:1-200](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java#L1-L200)
- [JwtAuthenticationFilter.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java#L1-L200)
- [TokenService.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java#L1-L200)
### 权限注解使用与最佳实践
- 接口级权限控制
- 在需要权限校验的方法上标注权限标识(如菜单code或按钮标识)
- 结合白名单跳过敏感接口校验
- 数据权限注解
- 在查询方法上标注 @DataScope,指定范围类型与目标表
- 确保 DataScopeTables 中已配置对应表的列映射
- 注意事项
- 避免在事务内频繁切换数据权限上下文
- 合理设置缓存失效时机,保证权限变更后即时生效
章节来源
- [DataScope.java:1-200](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java#L1-L200)
- [DataScopeTables.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java#L1-L200)
- [PermissionServiceImpl.java:1-200](file://crm-auth/src/main/java/com/crm/auth/service/impl/PermissionServiceImpl.java#L1-L200)
### 动态权限加载与缓存机制
- 动态加载
- 登录后根据用户角色拉取菜单树与按钮权限
- 将权限集合与菜单树写入缓存
- 缓存键设计
- 用户维度:user:{userId}:perms
- 角色维度:role:{roleId}:menuTree
- 缓存更新
- 角色/菜单变更触发失效
- 提供手动刷新接口供管理员使用
章节来源
- [PermissionServiceImpl.java:1-200](file://crm-auth/src/main/java/com/crm/auth/service/impl/PermissionServiceImpl.java#L1-L200)
- [SysMenuServiceImpl.java:1-200](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysMenuServiceImpl.java#L1-L200)
- [SysRoleServiceImpl.java:1-200](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysRoleServiceImpl.java#L1-L200)
### 配置方法与初始化
- 权限配置
- PermissionConfig:集中管理权限相关开关与默认值
- 安全配置
- SecurityConfig:URL白名单、跨域、异常处理器
- 数据初始化
- DataInitializer:初始化默认角色、菜单、管理员账号等
章节来源
- [PermissionConfig.java:1-200](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.java#L1-L200)
- [SecurityConfig.java:1-200](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java#L1-L200)
- [DataInitializer.java:1-200](file://crm-auth/src/main/java/com/crm/auth/config/DataInitializer.java#L1-L200)
## 依赖关系分析
- 模块依赖
- crm-auth 依赖 crm-base(异常、工具、数据可见性上下文)
- crm-app 依赖 crm-auth(作为应用入口)
- 组件耦合
- PermissionServiceImpl 依赖菜单与角色服务
- DataScopeInterceptor 依赖 DataScopeHelper 与 CrmSqlInjector
- SecurityConfig 依赖 JwtAuthenticationFilter 与异常处理器
```mermaid
graph LR
APP["crm-app"] --> AUTH["crm-auth"]
AUTH --> BASE["crm-base"]
AUTH --> |"依赖"| Mapper["Mapper层"]
AUTH --> |"依赖"| Service["Service层"]
Service --> |"依赖"| Mapper
```
图表来源
- [CrmAppApplication.java:1-200](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java#L1-L200)
- [AuthApplication.java:1-200](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java#L1-L200)
章节来源
- [CrmAppApplication.java:1-200](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java#L1-L200)
- [AuthApplication.java:1-200](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java#L1-L200)
## 性能考虑
- 缓存优先
- 菜单树与权限集合应缓存至Redis,降低重复查询
- 合理设置过期时间与失效策略
- 批量与懒加载
- 菜单树构建尽量使用批量查询与懒加载
- 数据权限SQL优化
- 在 DataScopeTables 中精确映射表与列,避免全表扫描
- 为常用过滤列添加索引
[本节为通用指导,不直接分析具体文件]
## 故障排查指南
- 常见错误
- 未认证或令牌过期:检查 JwtAuthenticationFilter 与 TokenService 配置
- 权限不足:确认角色-菜单授权是否正确,缓存是否及时失效
- 数据权限不生效:检查 @DataScope 注解与 DataScopeTables 映射
- 定位步骤
- 查看全局异常处理器输出
- 开启调试日志,观察拦截器与SQL注入过程
- 核对缓存键与失效时机
章节来源
- [GlobalExceptionHandlerAdvice.java:1-200](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java#L1-L200)
- [JwtAuthenticationFilter.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java#L1-L200)
- [TokenService.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java#L1-L200)
- [DataScopeInterceptor.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java#L1-L200)
- [DataScopeTables.java:1-200](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java#L1-L200)
## 结论
本权限管理系统以RBAC为核心,结合注解驱动的数据权限控制与拦截器实现的SQL改写,形成完整的权限校验与数据隔离方案。通过合理的缓存策略与配置化开关,可在保障安全性的同时提升性能与可维护性。建议在生产环境严格管理权限变更与缓存失效,确保权限一致性与实时性。
[本节为总结,不直接分析具体文件]
## 附录
- 术语
- RBAC:基于角色的访问控制
- 数据权限:基于用户所属组织或范围的查询限制
- 参考
- 实体与枚举:SysRole、SysMenu、DataScopeEnum
- 服务与拦截:PermissionServiceImpl、DataScopeInterceptor
- 配置与初始化:PermissionConfig、SecurityConfig、DataInitializer
[本节为补充信息,不直接分析具体文件]