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.
543 lines
30 KiB
543 lines
30 KiB
|
1 month ago
|
# 角色权限管理
|
||
|
|
|
||
|
|
<cite>
|
||
|
|
**本文引用的文件**
|
||
|
|
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
|
||
|
|
- [application.yml](file://crm-app/src/main/resources/application.yml)
|
||
|
|
- [AuthProperties.java](file://crm-auth/src/main/java/com/crm/auth/config/AuthProperties.java)
|
||
|
|
- [DataInitializer.java](file://crm-auth/src/main/java/com/crm/auth/config/DataInitializer.java)
|
||
|
|
- [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)
|
||
|
|
- [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)
|
||
|
|
- [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)
|
||
|
|
- [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)
|
||
|
|
- [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/ISysDeptService.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)
|
||
|
|
- [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)
|
||
|
|
- [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)
|
||
|
|
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java)
|
||
|
|
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.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)
|
||
|
|
- [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)
|
||
|
|
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
|
||
|
|
- [FileApi.java](file://crm-file/src/main/java/com/crm/file/api/FileApi.java)
|
||
|
|
- [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java)
|
||
|
|
- [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java)
|
||
|
|
- [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java)
|
||
|
|
- [IFileInfoService.java](file://crm-file/src/main/java/com/crm/file/service/IFileInfoService.java)
|
||
|
|
</cite>
|
||
|
|
|
||
|
|
## 目录
|
||
|
|
1. [简介](#简介)
|
||
|
|
2. [项目结构](#项目结构)
|
||
|
|
3. [核心组件](#核心组件)
|
||
|
|
4. [架构总览](#架构总览)
|
||
|
|
5. [详细组件分析](#详细组件分析)
|
||
|
|
6. [依赖关系分析](#依赖关系分析)
|
||
|
|
7. [性能与缓存优化](#性能与缓存优化)
|
||
|
|
8. [故障排查指南](#故障排查指南)
|
||
|
|
9. [结论](#结论)
|
||
|
|
10. [附录:最佳实践与常见场景](#附录最佳实践与常见场景)
|
||
|
|
|
||
|
|
## 简介
|
||
|
|
本技术文档围绕角色权限管理模块,系统性阐述基于RBAC(基于角色的访问控制)的权限模型设计与实现。内容涵盖角色定义、权限分配、用户-角色关联、数据范围控制、权限继承与合并、动态权限控制、权限缓存机制与性能优化策略,并提供常见业务场景的实现方案与最佳实践。读者可据此快速理解系统权限体系并指导二次开发。
|
||
|
|
|
||
|
|
## 项目结构
|
||
|
|
权限相关能力集中在 crm-auth 模块,基础安全与通用能力在 crm-base 模块,其他模块通过接口或配置接入。整体采用分层架构:
|
||
|
|
- 表现层:控制器暴露登录、鉴权、系统管理等API
|
||
|
|
- 服务层:封装认证、授权、角色菜单、部门等核心业务逻辑
|
||
|
|
- 数据层:MyBatis-Plus Mapper 映射实体到数据库
|
||
|
|
- 安全层:JWT过滤器、拦截器、异常处理、上下文工具
|
||
|
|
- 基础层:通用实体、枚举、异常、结果封装、数据可见性上下文、Redis配置、雪花ID等
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
graph TB
|
||
|
|
subgraph "应用入口"
|
||
|
|
App["CrmAppApplication"]
|
||
|
|
Yml["application.yml"]
|
||
|
|
end
|
||
|
|
subgraph "认证与授权(crm-auth)"
|
||
|
|
Cfg["SecurityConfig / PermissionConfig"]
|
||
|
|
Ctrl["AuthController / SystemController"]
|
||
|
|
Svc["AuthService / PermissionService / RoleService / MenuService"]
|
||
|
|
Sec["JwtAuthenticationFilter / DataScopeInterceptor / TokenService"]
|
||
|
|
Ent["SysRole / SysMenu / SysUserRole / SysRoleMenu / AuthUser / ..."]
|
||
|
|
Map["*Mapper 接口"]
|
||
|
|
end
|
||
|
|
subgraph "基础能力(crm-base)"
|
||
|
|
BaseEnt["BaseEntity / OwnedEntity"]
|
||
|
|
SecBase["LoginUser / SecurityUtils / DataScopeHelper / DataVisibilityContext"]
|
||
|
|
Redis["RedisConfig"]
|
||
|
|
Id["SnowflakeIdWorker"]
|
||
|
|
Ex["全局异常处理器 / 权限异常"]
|
||
|
|
end
|
||
|
|
subgraph "文件服务(crm-file)"
|
||
|
|
FileCtrl["FileController"]
|
||
|
|
FileSvc["IFileInfoService / FileInfoServiceImpl"]
|
||
|
|
end
|
||
|
|
App --> Cfg
|
||
|
|
Cfg --> Sec
|
||
|
|
Ctrl --> Svc
|
||
|
|
Svc --> Map
|
||
|
|
Map --> Ent
|
||
|
|
Sec --> SecBase
|
||
|
|
Svc --> Redis
|
||
|
|
FileCtrl --> FileSvc
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
|
||
|
|
- [application.yml](file://crm-app/src/main/resources/application.yml)
|
||
|
|
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
|
||
|
|
- [PermissionConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.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)
|
||
|
|
- [AuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
|
||
|
|
- [PermissionService.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/PermissionServiceImpl.java)
|
||
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.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)
|
||
|
|
- [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)
|
||
|
|
- [AuthUser.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthUser.java)
|
||
|
|
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.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)
|
||
|
|
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
|
||
|
|
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
|
||
|
|
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
|
||
|
|
- [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java)
|
||
|
|
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
|
||
|
|
- [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java)
|
||
|
|
- [IFileInfoService.java](file://crm-file/src/main/java/com/crm/file/service/IFileInfoService.java)
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
|
||
|
|
- [application.yml](file://crm-app/src/main/resources/application.yml)
|
||
|
|
|
||
|
|
## 核心组件
|
||
|
|
- 角色与菜单模型:角色、菜单、用户-角色、角色-菜单关联构成RBAC核心骨架
|
||
|
|
- 认证流程:JWT过滤器解析令牌,构建登录用户上下文
|
||
|
|
- 授权校验:方法级注解+拦截器/切面进行权限判定
|
||
|
|
- 数据范围控制:基于注解的数据范围拦截器,结合上下文注入SQL条件
|
||
|
|
- 权限缓存:角色-菜单、用户-角色、部门树等热点数据缓存于Redis
|
||
|
|
- 统一异常与结果:标准化错误码与响应体
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [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)
|
||
|
|
- [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)
|
||
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
|
||
|
|
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
|
||
|
|
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
|
||
|
|
- [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java)
|
||
|
|
- [PermissionErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/PermissionErrorException.java)
|
||
|
|
|
||
|
|
## 架构总览
|
||
|
|
下图展示从请求进入、认证、授权到数据范围控制的完整链路,以及缓存参与点。
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
sequenceDiagram
|
||
|
|
participant Client as "客户端"
|
||
|
|
participant API as "AuthController/SystemController"
|
||
|
|
participant Filter as "JwtAuthenticationFilter"
|
||
|
|
participant Svc as "AuthService/PermissionService"
|
||
|
|
participant Cache as "Redis(权限/角色/菜单/部门树)"
|
||
|
|
participant DB as "数据库"
|
||
|
|
participant Interceptor as "DataScopeInterceptor"
|
||
|
|
Client->>API : "HTTP请求"
|
||
|
|
API->>Filter : "进入安全过滤器链"
|
||
|
|
Filter->>Filter : "解析JWT/校验签名"
|
||
|
|
Filter->>Svc : "加载用户角色与权限"
|
||
|
|
Svc->>Cache : "读取缓存(命中则返回)"
|
||
|
|
alt 缓存未命中
|
||
|
|
Svc->>DB : "查询用户-角色、角色-菜单"
|
||
|
|
DB-->>Svc : "原始数据"
|
||
|
|
Svc->>Cache : "写入缓存"
|
||
|
|
end
|
||
|
|
Filter-->>API : "设置Security上下文"
|
||
|
|
API->>Svc : "调用业务方法(含权限注解)"
|
||
|
|
Svc->>Interceptor : "数据范围拦截"
|
||
|
|
Interceptor->>Cache : "读取数据范围配置"
|
||
|
|
Interceptor->>DB : "拼接WHERE条件执行"
|
||
|
|
Interceptor-->>Svc : "返回受限数据集"
|
||
|
|
Svc-->>API : "业务结果"
|
||
|
|
API-->>Client : "JSON响应"
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [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)
|
||
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
||
|
|
- [PermissionServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/PermissionServiceImpl.java)
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
|
||
|
|
|
||
|
|
## 详细组件分析
|
||
|
|
|
||
|
|
### RBAC数据模型与关系
|
||
|
|
- 角色(SysRole):定义一组权限集合
|
||
|
|
- 菜单(SysMenu):代表系统功能节点(按钮/页面/接口),支持层级
|
||
|
|
- 用户-角色(SysUserRole):多对多关联
|
||
|
|
- 角色-菜单(SysRoleMenu):多对多关联
|
||
|
|
- 用户(AuthUser)、部门(SysDept)、用户-部门(SysUserDept):用于数据范围控制
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
erDiagram
|
||
|
|
SYS_ROLE {
|
||
|
|
bigint id PK
|
||
|
|
varchar name
|
||
|
|
varchar code
|
||
|
|
int status
|
||
|
|
datetime created_at
|
||
|
|
datetime updated_at
|
||
|
|
}
|
||
|
|
SYS_MENU {
|
||
|
|
bigint id PK
|
||
|
|
varchar name
|
||
|
|
varchar path
|
||
|
|
int type
|
||
|
|
int sort
|
||
|
|
bigint parent_id FK
|
||
|
|
datetime created_at
|
||
|
|
datetime updated_at
|
||
|
|
}
|
||
|
|
AUTH_USER {
|
||
|
|
bigint id PK
|
||
|
|
varchar username
|
||
|
|
varchar password
|
||
|
|
int status
|
||
|
|
datetime created_at
|
||
|
|
datetime updated_at
|
||
|
|
}
|
||
|
|
SYS_DEPT {
|
||
|
|
bigint id PK
|
||
|
|
varchar name
|
||
|
|
bigint parent_id FK
|
||
|
|
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 : "包含"
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [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)
|
||
|
|
- [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)
|
||
|
|
- [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)
|
||
|
|
- [SysUserDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserDept.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)
|
||
|
|
- [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)
|
||
|
|
- [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)
|
||
|
|
- [SysUserDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserDept.java)
|
||
|
|
|
||
|
|
### 认证与授权流程
|
||
|
|
- 登录:控制器接收参数,服务层校验身份,生成JWT并返回
|
||
|
|
- 鉴权:过滤器解析JWT,构造登录用户上下文;服务层加载用户角色与权限,优先读缓存,未命中回源DB并回填缓存
|
||
|
|
- 授权:方法级注解驱动,拦截器根据当前用户权限集合判断是否允许访问
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
sequenceDiagram
|
||
|
|
participant Client as "客户端"
|
||
|
|
participant AuthCtrl as "AuthController"
|
||
|
|
participant AuthService as "AuthService"
|
||
|
|
participant PermSvc as "PermissionService"
|
||
|
|
participant JWT as "JwtAuthenticationFilter"
|
||
|
|
participant Cache as "Redis"
|
||
|
|
participant DB as "数据库"
|
||
|
|
Client->>AuthCtrl : "POST /auth/login"
|
||
|
|
AuthCtrl->>AuthService : "login(LoginParam)"
|
||
|
|
AuthService->>DB : "校验用户名/密码"
|
||
|
|
AuthService-->>AuthCtrl : "用户信息"
|
||
|
|
AuthService->>PermSvc : "获取用户角色与权限"
|
||
|
|
PermSvc->>Cache : "读取缓存"
|
||
|
|
alt 未命中
|
||
|
|
PermSvc->>DB : "查询用户-角色、角色-菜单"
|
||
|
|
DB-->>PermSvc : "数据"
|
||
|
|
PermSvc->>Cache : "写入缓存"
|
||
|
|
end
|
||
|
|
AuthService-->>AuthCtrl : "生成JWT"
|
||
|
|
AuthCtrl-->>Client : "{token, userInfo}"
|
||
|
|
Client->>JWT : "携带Token访问受保护接口"
|
||
|
|
JWT->>JWT : "解析并校验Token"
|
||
|
|
JWT->>PermSvc : "加载权限(带缓存)"
|
||
|
|
JWT-->>Client : "放行或拒绝"
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
|
||
|
|
- [AuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
|
||
|
|
- [PermissionServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/PermissionServiceImpl.java)
|
||
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
||
|
|
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
|
||
|
|
- [AuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
|
||
|
|
- [PermissionServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/PermissionServiceImpl.java)
|
||
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
||
|
|
|
||
|
|
### 数据范围控制(行级权限)
|
||
|
|
- 注解驱动:使用自定义注解声明数据范围级别
|
||
|
|
- 上下文:将当前用户、组织、角色等信息放入可见性上下文
|
||
|
|
- 拦截器:在查询前注入WHERE条件,限制数据可见范围
|
||
|
|
- 枚举:定义数据范围类型(如本人、本部门、本部门及子部门、全部等)
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
flowchart TD
|
||
|
|
Start(["进入查询方法"]) --> CheckAnno["检查@DataScope注解"]
|
||
|
|
CheckAnno --> HasAnno{"存在注解?"}
|
||
|
|
HasAnno --> |否| Proceed["直接执行查询"]
|
||
|
|
HasAnno --> |是| BuildCtx["构建数据可见性上下文"]
|
||
|
|
BuildCtx --> ReadScope["读取数据范围级别"]
|
||
|
|
ReadScope --> InjectSql["拼接WHERE条件"]
|
||
|
|
InjectSql --> ExecQuery["执行SQL"]
|
||
|
|
ExecQuery --> End(["返回受限结果集"])
|
||
|
|
Proceed --> End
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [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)
|
||
|
|
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
|
||
|
|
- [DataScopeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.java)
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.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)
|
||
|
|
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
|
||
|
|
- [DataScopeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.java)
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
|
||
|
|
### 权限缓存与刷新
|
||
|
|
- 缓存对象:用户权限集合、角色-菜单映射、部门树
|
||
|
|
- 缓存键设计:以用户ID、角色ID、部门ID等为维度
|
||
|
|
- 更新策略:角色/菜单/用户-角色变更时,主动失效相关缓存
|
||
|
|
- 降级策略:缓存不可用时回源DB,保证可用性
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
classDiagram
|
||
|
|
class 权限缓存管理器 {
|
||
|
|
+getPermissions(userId) Set~String~
|
||
|
|
+getRoleMenus(roleId) Set~Long~
|
||
|
|
+getDeptTree(deptId) Dept[]
|
||
|
|
+invalidateByUser(userId)
|
||
|
|
+invalidateByRole(roleId)
|
||
|
|
+invalidateByDept(deptId)
|
||
|
|
}
|
||
|
|
class Redis配置 {
|
||
|
|
+连接池
|
||
|
|
+序列化策略
|
||
|
|
+过期策略
|
||
|
|
}
|
||
|
|
class 权限服务 {
|
||
|
|
+loadUserPermissions(userId)
|
||
|
|
+syncToCache()
|
||
|
|
}
|
||
|
|
权限缓存管理器 --> Redis配置 : "使用"
|
||
|
|
权限服务 --> 权限缓存管理器 : "读写"
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [PermissionServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/PermissionServiceImpl.java)
|
||
|
|
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
|
||
|
|
- [DeptTreeCache.java](file://crm-auth/src/main/java/com/crm/auth/service/DeptTreeCache.java)
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [PermissionServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/PermissionServiceImpl.java)
|
||
|
|
- [DeptTreeCache.java](file://crm-auth/src/main/java/com/crm/auth/service/DeptTreeCache.java)
|
||
|
|
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
|
||
|
|
|
||
|
|
### 动态权限控制
|
||
|
|
- 方法级注解:在控制器或服务方法上声明所需权限标识
|
||
|
|
- 运行时判定:拦截器/切面读取当前用户权限集合进行匹配
|
||
|
|
- 细粒度控制:支持资源级(菜单/按钮)与操作级(增删改查)组合
|
||
|
|
- 扩展点:新增权限标识无需重启,仅需配置与缓存刷新
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
|
||
|
|
- [PermissionConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.java)
|
||
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
|
||
|
|
## 依赖关系分析
|
||
|
|
- 控制器依赖服务层,服务层依赖Mapper与缓存
|
||
|
|
- 安全过滤器依赖服务层加载权限,依赖Redis缓存
|
||
|
|
- 数据范围拦截器依赖上下文与枚举,影响所有查询路径
|
||
|
|
- 基础模块提供通用实体、异常、结果、工具类与安全上下文
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
graph LR
|
||
|
|
Ctrl["控制器层"] --> Svc["服务层"]
|
||
|
|
Svc --> Mapper["Mapper层"]
|
||
|
|
Svc --> Cache["Redis缓存"]
|
||
|
|
Filter["安全过滤器"] --> Svc
|
||
|
|
Interceptor["数据范围拦截器"] --> Context["可见性上下文"]
|
||
|
|
Svc --> Base["基础模块(BaseEntity/异常/结果)"]
|
||
|
|
```
|
||
|
|
|
||
|
|
图表来源
|
||
|
|
- [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)
|
||
|
|
- [AuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
|
||
|
|
- [PermissionServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/PermissionServiceImpl.java)
|
||
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.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)
|
||
|
|
- [AuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
|
||
|
|
- [PermissionServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/PermissionServiceImpl.java)
|
||
|
|
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
|
||
|
|
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
|
||
|
|
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
|
||
|
|
|
||
|
|
## 性能与缓存优化
|
||
|
|
- 热点数据缓存:用户权限、角色-菜单、部门树均落Redis,降低DB压力
|
||
|
|
- 批量查询:角色-菜单、用户-角色采用批量聚合,减少往返次数
|
||
|
|
- 懒加载与按需加载:仅在首次访问或缓存失效时加载
|
||
|
|
- 合理过期:为不同缓存设置差异化TTL,避免雪崩
|
||
|
|
- 防穿透:空值缓存与布隆过滤器(可选)
|
||
|
|
- 降级与熔断:缓存不可用自动回源,保障可用性
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
|
||
|
|
- [PermissionServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/PermissionServiceImpl.java)
|
||
|
|
- [DeptTreeCache.java](file://crm-auth/src/main/java/com/crm/auth/service/DeptTreeCache.java)
|
||
|
|
|
||
|
|
## 故障排查指南
|
||
|
|
- 登录失败:检查用户名/密码、第三方登录配置、Token生成逻辑
|
||
|
|
- 鉴权失败:确认用户是否具备对应角色与权限,检查缓存一致性
|
||
|
|
- 数据范围异常:核对@DataScope注解与上下文是否正确注入
|
||
|
|
- 缓存问题:检查Redis连通性、序列化、过期策略与失效时机
|
||
|
|
- 统一异常:查看全局异常处理器输出,定位具体错误码与堆栈
|
||
|
|
|
||
|
|
章节来源
|
||
|
|
- [SecurityExceptionHandlers.java](file://crm-auth/src/main/java/com/crm/auth/security/SecurityExceptionHandlers.java)
|
||
|
|
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
|
||
|
|
- [PermissionErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/PermissionErrorException.java)
|
||
|
|
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
|
||
|
|
|
||
|
|
## 结论
|
||
|
|
本权限模块以RBAC为核心,结合JWT认证、方法级注解授权、数据范围控制与Redis缓存,形成高内聚、低耦合、可扩展的权限体系。通过合理的缓存策略与异常处理,兼顾了性能与稳定性。后续可在权限继承、动态策略引擎等方面进一步增强。
|
||
|
|
|
||
|
|
## 附录:最佳实践与常见场景
|
||
|
|
- 角色设计
|
||
|
|
- 角色命名规范:按领域/岗位划分,避免过细粒度过多角色
|
||
|
|
- 角色继承:通过父角色聚合权限,子角色继承父角色权限集合
|
||
|
|
- 权限合并:用户最终权限为用户所有角色权限的并集
|
||
|
|
- 权限分配
|
||
|
|
- 菜单与按钮分离:菜单控制导航,按钮控制操作
|
||
|
|
- 最小权限原则:仅授予必要权限
|
||
|
|
- 定期审计:清理僵尸角色与冗余权限
|
||
|
|
- 用户-角色关联
|
||
|
|
- 批量赋权:导入模板批量分配
|
||
|
|
- 动态调整:在线修改即时生效(配合缓存刷新)
|
||
|
|
- 数据范围
|
||
|
|
- 默认“本人”,逐步放宽至“本部门”“本部门及子部门”“全部”
|
||
|
|
- 跨部门协作:通过临时授权或共享数据表字段控制
|
||
|
|
- 动态权限
|
||
|
|
- 开关式权限:通过配置中心或数据库开关控制功能可见性
|
||
|
|
- 灰度发布:按租户/部门逐步开放新功能
|
||
|
|
- 缓存策略
|
||
|
|
- 键设计:user:perms:{userId}, role:menus:{roleId}, dept:tree:{deptId}
|
||
|
|
- 失效策略:写后失效,定时全量重建
|
||
|
|
- 监控告警:命中率、延迟、内存占用监控
|
||
|
|
- 常见问题
|
||
|
|
- 权限不生效:检查缓存是否同步、注解是否遗漏
|
||
|
|
- 数据越权:核查数据范围拦截器是否生效
|
||
|
|
- 登录慢:检查第三方登录耗时、权限加载耗时
|
||
|
|
|
||
|
|
[本节为概念性总结,不直接分析具体文件]
|